summary refs log tree commit diff
path: root/tests/ui/span
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/ui/span
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/ui/span')
-rw-r--r--tests/ui/span/E0046.rs11
-rw-r--r--tests/ui/span/E0046.stderr12
-rw-r--r--tests/ui/span/E0072.rs7
-rw-r--r--tests/ui/span/E0072.stderr17
-rw-r--r--tests/ui/span/E0204.rs26
-rw-r--r--tests/ui/span/E0204.stderr43
-rw-r--r--tests/ui/span/E0493.rs21
-rw-r--r--tests/ui/span/E0493.stderr11
-rw-r--r--tests/ui/span/E0535.rs6
-rw-r--r--tests/ui/span/E0535.stderr11
-rw-r--r--tests/ui/span/E0536.rs4
-rw-r--r--tests/ui/span/E0536.stderr9
-rw-r--r--tests/ui/span/E0537.rs4
-rw-r--r--tests/ui/span/E0537.stderr9
-rw-r--r--tests/ui/span/auxiliary/transitive_dep_three.rs9
-rw-r--r--tests/ui/span/auxiliary/transitive_dep_two.rs3
-rw-r--r--tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs142
-rw-r--r--tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr112
-rw-r--r--tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs60
-rw-r--r--tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr47
-rw-r--r--tests/ui/span/borrowck-call-is-borrow-issue-12224.rs62
-rw-r--r--tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr61
-rw-r--r--tests/ui/span/borrowck-call-method-from-mut-aliasable.rs21
-rw-r--r--tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr14
-rw-r--r--tests/ui/span/borrowck-fn-in-const-b.rs14
-rw-r--r--tests/ui/span/borrowck-fn-in-const-b.stderr14
-rw-r--r--tests/ui/span/borrowck-let-suggestion-suffixes.rs59
-rw-r--r--tests/ui/span/borrowck-let-suggestion-suffixes.stderr63
-rw-r--r--tests/ui/span/borrowck-object-mutability.rs26
-rw-r--r--tests/ui/span/borrowck-object-mutability.stderr25
-rw-r--r--tests/ui/span/borrowck-ref-into-rvalue.fixed13
-rw-r--r--tests/ui/span/borrowck-ref-into-rvalue.rs12
-rw-r--r--tests/ui/span/borrowck-ref-into-rvalue.stderr20
-rw-r--r--tests/ui/span/coerce-suggestions.rs23
-rw-r--r--tests/ui/span/coerce-suggestions.stderr72
-rw-r--r--tests/ui/span/destructor-restrictions.rs11
-rw-r--r--tests/ui/span/destructor-restrictions.stderr23
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs18
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr95
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs15
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr24
-rw-r--r--tests/ui/span/dropck-object-cycle.rs47
-rw-r--r--tests/ui/span/dropck-object-cycle.stderr15
-rw-r--r--tests/ui/span/dropck_arr_cycle_checked.rs106
-rw-r--r--tests/ui/span/dropck_arr_cycle_checked.stderr43
-rw-r--r--tests/ui/span/dropck_direct_cycle_with_drop.rs44
-rw-r--r--tests/ui/span/dropck_direct_cycle_with_drop.stderr29
-rw-r--r--tests/ui/span/dropck_misc_variants.rs37
-rw-r--r--tests/ui/span/dropck_misc_variants.stderr30
-rw-r--r--tests/ui/span/dropck_vec_cycle_checked.rs111
-rw-r--r--tests/ui/span/dropck_vec_cycle_checked.stderr43
-rw-r--r--tests/ui/span/gated-features-attr-spans.rs7
-rw-r--r--tests/ui/span/gated-features-attr-spans.stderr12
-rw-r--r--tests/ui/span/impl-wrong-item-for-trait.rs38
-rw-r--r--tests/ui/span/impl-wrong-item-for-trait.stderr66
-rw-r--r--tests/ui/span/import-ty-params.rs23
-rw-r--r--tests/ui/span/import-ty-params.stderr20
-rw-r--r--tests/ui/span/issue-11925.rs13
-rw-r--r--tests/ui/span/issue-11925.stderr9
-rw-r--r--tests/ui/span/issue-15480.fixed14
-rw-r--r--tests/ui/span/issue-15480.rs13
-rw-r--r--tests/ui/span/issue-15480.stderr21
-rw-r--r--tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs28
-rw-r--r--tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr44
-rw-r--r--tests/ui/span/issue-23729.rs33
-rw-r--r--tests/ui/span/issue-23729.stderr11
-rw-r--r--tests/ui/span/issue-23827.rs33
-rw-r--r--tests/ui/span/issue-23827.stderr11
-rw-r--r--tests/ui/span/issue-24356.rs27
-rw-r--r--tests/ui/span/issue-24356.stderr11
-rw-r--r--tests/ui/span/issue-24690.rs16
-rw-r--r--tests/ui/span/issue-24690.stderr29
-rw-r--r--tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs37
-rw-r--r--tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr17
-rw-r--r--tests/ui/span/issue-24805-dropck-trait-has-items.rs57
-rw-r--r--tests/ui/span/issue-24805-dropck-trait-has-items.stderr42
-rw-r--r--tests/ui/span/issue-24895-copy-clone-dropck.rs29
-rw-r--r--tests/ui/span/issue-24895-copy-clone-dropck.stderr16
-rw-r--r--tests/ui/span/issue-25199.rs74
-rw-r--r--tests/ui/span/issue-25199.stderr15
-rw-r--r--tests/ui/span/issue-26656.rs42
-rw-r--r--tests/ui/span/issue-26656.stderr16
-rw-r--r--tests/ui/span/issue-27522.rs9
-rw-r--r--tests/ui/span/issue-27522.stderr12
-rw-r--r--tests/ui/span/issue-29106.rs26
-rw-r--r--tests/ui/span/issue-29106.stderr29
-rw-r--r--tests/ui/span/issue-29595.rs7
-rw-r--r--tests/ui/span/issue-29595.stderr9
-rw-r--r--tests/ui/span/issue-33884.rs18
-rw-r--r--tests/ui/span/issue-33884.stderr11
-rw-r--r--tests/ui/span/issue-34264.rs11
-rw-r--r--tests/ui/span/issue-34264.stderr102
-rw-r--r--tests/ui/span/issue-35987.rs14
-rw-r--r--tests/ui/span/issue-35987.stderr19
-rw-r--r--tests/ui/span/issue-36537.rs14
-rw-r--r--tests/ui/span/issue-36537.stderr14
-rw-r--r--tests/ui/span/issue-37767.rs41
-rw-r--r--tests/ui/span/issue-37767.stderr78
-rw-r--r--tests/ui/span/issue-39018.rs38
-rw-r--r--tests/ui/span/issue-39018.stderr194
-rw-r--r--tests/ui/span/issue-39698.rs16
-rw-r--r--tests/ui/span/issue-39698.stderr43
-rw-r--r--tests/ui/span/issue-40157.rs4
-rw-r--r--tests/ui/span/issue-40157.stderr13
-rw-r--r--tests/ui/span/issue-42234-unknown-receiver-type.full.stderr27
-rw-r--r--tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr27
-rw-r--r--tests/ui/span/issue-42234-unknown-receiver-type.rs19
-rw-r--r--tests/ui/span/issue-43927-non-ADT-derive.rs6
-rw-r--r--tests/ui/span/issue-43927-non-ADT-derive.stderr21
-rw-r--r--tests/ui/span/issue-71363.rs19
-rw-r--r--tests/ui/span/issue-71363.stderr29
-rw-r--r--tests/ui/span/issue-81800.rs2
-rw-r--r--tests/ui/span/issue-81800.stderr19
-rw-r--r--tests/ui/span/issue28498-reject-ex1.rs37
-rw-r--r--tests/ui/span/issue28498-reject-ex1.stderr17
-rw-r--r--tests/ui/span/issue28498-reject-lifetime-param.rs36
-rw-r--r--tests/ui/span/issue28498-reject-lifetime-param.stderr17
-rw-r--r--tests/ui/span/issue28498-reject-passed-to-fn.rs38
-rw-r--r--tests/ui/span/issue28498-reject-passed-to-fn.stderr17
-rw-r--r--tests/ui/span/issue28498-reject-trait-bound.rs38
-rw-r--r--tests/ui/span/issue28498-reject-trait-bound.stderr17
-rw-r--r--tests/ui/span/lint-unused-unsafe-thir.rs61
-rw-r--r--tests/ui/span/lint-unused-unsafe-thir.stderr50
-rw-r--r--tests/ui/span/lint-unused-unsafe.mir.stderr1402
-rw-r--r--tests/ui/span/lint-unused-unsafe.rs1100
-rw-r--r--tests/ui/span/macro-span-replacement.rs13
-rw-r--r--tests/ui/span/macro-span-replacement.stderr19
-rw-r--r--tests/ui/span/macro-ty-params.rs15
-rw-r--r--tests/ui/span/macro-ty-params.stderr26
-rw-r--r--tests/ui/span/method-and-field-eager-resolution.rs15
-rw-r--r--tests/ui/span/method-and-field-eager-resolution.stderr31
-rw-r--r--tests/ui/span/missing-unit-argument.rs17
-rw-r--r--tests/ui/span/missing-unit-argument.stderr96
-rw-r--r--tests/ui/span/move-closure.rs6
-rw-r--r--tests/ui/span/move-closure.stderr18
-rw-r--r--tests/ui/span/multiline-span-E0072.rs10
-rw-r--r--tests/ui/span/multiline-span-E0072.stderr18
-rw-r--r--tests/ui/span/multiline-span-simple.rs20
-rw-r--r--tests/ui/span/multiline-span-simple.stderr16
-rw-r--r--tests/ui/span/multispan-import-lint.rs10
-rw-r--r--tests/ui/span/multispan-import-lint.stderr15
-rw-r--r--tests/ui/span/mut-arg-hint.rs22
-rw-r--r--tests/ui/span/mut-arg-hint.stderr36
-rw-r--r--tests/ui/span/mut-ptr-cant-outlive-ref.rs15
-rw-r--r--tests/ui/span/mut-ptr-cant-outlive-ref.stderr14
-rw-r--r--tests/ui/span/non-existing-module-import.rs3
-rw-r--r--tests/ui/span/non-existing-module-import.stderr9
-rw-r--r--tests/ui/span/pub-struct-field.rs10
-rw-r--r--tests/ui/span/pub-struct-field.stderr20
-rw-r--r--tests/ui/span/range-2.rs15
-rw-r--r--tests/ui/span/range-2.stderr25
-rw-r--r--tests/ui/span/recursive-type-field.rs18
-rw-r--r--tests/ui/span/recursive-type-field.stderr27
-rw-r--r--tests/ui/span/regionck-unboxed-closure-lifetimes.rs16
-rw-r--r--tests/ui/span/regionck-unboxed-closure-lifetimes.stderr14
-rw-r--r--tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs16
-rw-r--r--tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr16
-rw-r--r--tests/ui/span/regions-close-over-type-parameter-2.rs27
-rw-r--r--tests/ui/span/regions-close-over-type-parameter-2.stderr13
-rw-r--r--tests/ui/span/regions-escape-loop-via-variable.rs14
-rw-r--r--tests/ui/span/regions-escape-loop-via-variable.stderr13
-rw-r--r--tests/ui/span/regions-escape-loop-via-vec.rs13
-rw-r--r--tests/ui/span/regions-escape-loop-via-vec.stderr50
-rw-r--r--tests/ui/span/regions-infer-borrow-scope-within-loop.rs22
-rw-r--r--tests/ui/span/regions-infer-borrow-scope-within-loop.stderr14
-rw-r--r--tests/ui/span/send-is-not-static-ensures-scoping.rs26
-rw-r--r--tests/ui/span/send-is-not-static-ensures-scoping.stderr29
-rw-r--r--tests/ui/span/send-is-not-static-std-sync-2.rs39
-rw-r--r--tests/ui/span/send-is-not-static-std-sync-2.stderr37
-rw-r--r--tests/ui/span/send-is-not-static-std-sync.rs55
-rw-r--r--tests/ui/span/send-is-not-static-std-sync.stderr72
-rw-r--r--tests/ui/span/slice-borrow.rs14
-rw-r--r--tests/ui/span/slice-borrow.stderr17
-rw-r--r--tests/ui/span/suggestion-non-ascii.rs4
-rw-r--r--tests/ui/span/suggestion-non-ascii.stderr9
-rw-r--r--tests/ui/span/transitive-dep-span.rs15
-rw-r--r--tests/ui/span/transitive-dep-span.stderr18
-rw-r--r--tests/ui/span/type-annotations-needed-expr.rs3
-rw-r--r--tests/ui/span/type-annotations-needed-expr.stderr14
-rw-r--r--tests/ui/span/type-binding.rs9
-rw-r--r--tests/ui/span/type-binding.stderr9
-rw-r--r--tests/ui/span/typo-suggestion.rs9
-rw-r--r--tests/ui/span/typo-suggestion.stderr15
-rw-r--r--tests/ui/span/unused-warning-point-at-identifier.rs30
-rw-r--r--tests/ui/span/unused-warning-point-at-identifier.stderr33
-rw-r--r--tests/ui/span/vec-must-not-hide-type-from-dropck.rs125
-rw-r--r--tests/ui/span/vec-must-not-hide-type-from-dropck.stderr29
-rw-r--r--tests/ui/span/vec_refs_data_with_early_death.rs33
-rw-r--r--tests/ui/span/vec_refs_data_with_early_death.stderr31
-rw-r--r--tests/ui/span/visibility-ty-params.rs13
-rw-r--r--tests/ui/span/visibility-ty-params.stderr21
-rw-r--r--tests/ui/span/wf-method-late-bound-regions.rs24
-rw-r--r--tests/ui/span/wf-method-late-bound-regions.stderr14
193 files changed, 7833 insertions, 0 deletions
diff --git a/tests/ui/span/E0046.rs b/tests/ui/span/E0046.rs
new file mode 100644
index 00000000000..96110989268
--- /dev/null
+++ b/tests/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/tests/ui/span/E0046.stderr b/tests/ui/span/E0046.stderr
new file mode 100644
index 00000000000..1323524f208
--- /dev/null
+++ b/tests/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/tests/ui/span/E0072.rs b/tests/ui/span/E0072.rs
new file mode 100644
index 00000000000..bc284cdcb47
--- /dev/null
+++ b/tests/ui/span/E0072.rs
@@ -0,0 +1,7 @@
+struct ListNode { //~ ERROR has infinite size
+    head: u8,
+    tail: Option<ListNode>,
+}
+
+fn main() {
+}
diff --git a/tests/ui/span/E0072.stderr b/tests/ui/span/E0072.stderr
new file mode 100644
index 00000000000..20f2e0df05e
--- /dev/null
+++ b/tests/ui/span/E0072.stderr
@@ -0,0 +1,17 @@
+error[E0072]: recursive type `ListNode` has infinite size
+  --> $DIR/E0072.rs:1:1
+   |
+LL | struct ListNode {
+   | ^^^^^^^^^^^^^^^
+LL |     head: u8,
+LL |     tail: Option<ListNode>,
+   |                  -------- recursive without indirection
+   |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+   |
+LL |     tail: Option<Box<ListNode>>,
+   |                  ++++        +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/ui/span/E0204.rs b/tests/ui/span/E0204.rs
new file mode 100644
index 00000000000..174de8cdd63
--- /dev/null
+++ b/tests/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/tests/ui/span/E0204.stderr b/tests/ui/span/E0204.stderr
new file mode 100644
index 00000000000..0b2166eed7e
--- /dev/null
+++ b/tests/ui/span/E0204.stderr
@@ -0,0 +1,43 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/E0204.rs:5:15
+   |
+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`
+   |
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/E0204.rs:17:15
+   |
+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`
+   |
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/span/E0493.rs b/tests/ui/span/E0493.rs
new file mode 100644
index 00000000000..625da25a7c2
--- /dev/null
+++ b/tests/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;
+//~^ ERROR destructor of
+
+fn main() {
+}
diff --git a/tests/ui/span/E0493.stderr b/tests/ui/span/E0493.stderr
new file mode 100644
index 00000000000..9db627562d6
--- /dev/null
+++ b/tests/ui/span/E0493.stderr
@@ -0,0 +1,11 @@
+error[E0493]: destructor of `(Foo, Foo)` cannot be evaluated at compile-time
+  --> $DIR/E0493.rs:17:17
+   |
+LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - value is dropped here
+   |                 |
+   |                 the destructor for this type cannot be evaluated in constants
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/span/E0535.rs b/tests/ui/span/E0535.rs
new file mode 100644
index 00000000000..e26334e9bbd
--- /dev/null
+++ b/tests/ui/span/E0535.rs
@@ -0,0 +1,6 @@
+#[inline(unknown)] //~ ERROR E0535
+pub fn something() {}
+
+fn main() {
+    something();
+}
diff --git a/tests/ui/span/E0535.stderr b/tests/ui/span/E0535.stderr
new file mode 100644
index 00000000000..b1411bc436a
--- /dev/null
+++ b/tests/ui/span/E0535.stderr
@@ -0,0 +1,11 @@
+error[E0535]: invalid argument
+  --> $DIR/E0535.rs:1:10
+   |
+LL | #[inline(unknown)]
+   |          ^^^^^^^
+   |
+   = help: valid inline arguments are `always` and `never`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0535`.
diff --git a/tests/ui/span/E0536.rs b/tests/ui/span/E0536.rs
new file mode 100644
index 00000000000..72de7b6f453
--- /dev/null
+++ b/tests/ui/span/E0536.rs
@@ -0,0 +1,4 @@
+#[cfg(not())] //~ ERROR E0536
+pub fn something() {}
+
+pub fn main() {}
diff --git a/tests/ui/span/E0536.stderr b/tests/ui/span/E0536.stderr
new file mode 100644
index 00000000000..820b0d7441b
--- /dev/null
+++ b/tests/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/tests/ui/span/E0537.rs b/tests/ui/span/E0537.rs
new file mode 100644
index 00000000000..4088a9ae53a
--- /dev/null
+++ b/tests/ui/span/E0537.rs
@@ -0,0 +1,4 @@
+#[cfg(unknown())] //~ ERROR E0537
+pub fn something() {}
+
+pub fn main() {}
diff --git a/tests/ui/span/E0537.stderr b/tests/ui/span/E0537.stderr
new file mode 100644
index 00000000000..5478c3fbcdd
--- /dev/null
+++ b/tests/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/tests/ui/span/auxiliary/transitive_dep_three.rs b/tests/ui/span/auxiliary/transitive_dep_three.rs
new file mode 100644
index 00000000000..99b51625ac3
--- /dev/null
+++ b/tests/ui/span/auxiliary/transitive_dep_three.rs
@@ -0,0 +1,9 @@
+#[macro_export]
+macro_rules! define_parse_error {
+    () => {
+        #[macro_export]
+        macro_rules! parse_error {
+            () => { parse error }
+        }
+    }
+}
diff --git a/tests/ui/span/auxiliary/transitive_dep_two.rs b/tests/ui/span/auxiliary/transitive_dep_two.rs
new file mode 100644
index 00000000000..5110c42765b
--- /dev/null
+++ b/tests/ui/span/auxiliary/transitive_dep_two.rs
@@ -0,0 +1,3 @@
+extern crate transitive_dep_three;
+
+transitive_dep_three::define_parse_error!();
diff --git a/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs
new file mode 100644
index 00000000000..76a1d12ea94
--- /dev/null
+++ b/tests/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/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
new file mode 100644
index 00000000000..570328fc211
--- /dev/null
+++ b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
@@ -0,0 +1,112 @@
+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 |     let __isize = &mut x.y;
+   |                        ^ cannot borrow as mutable
+   |
+help: consider changing this to be mutable
+   |
+LL | fn deref_mut_field1(mut x: Own<Point>) {
+   |                     +++
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:65:10
+   |
+LL |     &mut x.y
+   |          ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn deref_extend_mut_field1(x: &mut Own<Point>) -> &mut isize {
+   |                               ~~~~~~~~~~~~~~~
+
+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 |     x.y = 3;
+   |     ^ cannot borrow as mutable
+   |
+help: consider changing this to be mutable
+   |
+LL | fn assign_field1<'a>(mut x: Own<Point>) {
+   |                      +++
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:92:5
+   |
+LL |     x.y = 3;
+   |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn assign_field2<'a>(x: &'a mut Own<Point>) {
+   |                         ~~~~~~~~~~~~~~~~~~
+
+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 |     x.set(0, 0);
+   |     ^^^^^^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to be mutable
+   |
+LL | fn deref_mut_method1(mut x: Own<Point>) {
+   |                      +++
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:121:5
+   |
+LL |     x.y_mut()
+   |     ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn deref_extend_mut_method1(x: &mut Own<Point>) -> &mut isize {
+   |                                ~~~~~~~~~~~~~~~
+
+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 |     *x.y_mut() = 3;
+   |      ^^^^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to be mutable
+   |
+LL | fn assign_method1<'a>(mut x: Own<Point>) {
+   |                       +++
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:133:6
+   |
+LL |     *x.y_mut() = 3;
+   |      ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn assign_method2<'a>(x: &'a mut Own<Point>) {
+   |                          ~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0499, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs
new file mode 100644
index 00000000000..8d43d5da430
--- /dev/null
+++ b/tests/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/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
new file mode 100644
index 00000000000..3fed7b3f4dc
--- /dev/null
+++ b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
@@ -0,0 +1,47 @@
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:29:25
+   |
+LL |     let __isize = &mut *x;
+   |                         ^ cannot borrow as mutable
+   |
+help: consider changing this to be mutable
+   |
+LL | fn deref_mut1(mut x: Own<isize>) {
+   |               +++
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:41:11
+   |
+LL |     &mut **x
+   |           ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn deref_extend_mut1<'a>(x: &'a mut Own<isize>) -> &'a mut isize {
+   |                             ~~~~~~~~~~~~~~~~~~
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:49:6
+   |
+LL |     *x = 3;
+   |      ^ cannot borrow as mutable
+   |
+help: consider changing this to be mutable
+   |
+LL | fn assign1<'a>(mut x: Own<isize>) {
+   |                +++
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:53:6
+   |
+LL |     **x = 3;
+   |      ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn assign2<'a>(x: &'a mut Own<isize>) {
+   |                   ~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.rs b/tests/ui/span/borrowck-call-is-borrow-issue-12224.rs
new file mode 100644
index 00000000000..938fdaf11f0
--- /dev/null
+++ b/tests/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<dyn FnMut() + 'a>;
+
+struct Test<'a> {
+    f: Box<dyn 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 `*f` as mutable, as it is behind a `&` reference
+}
+
+fn test3<F>(f: &mut F) where F: FnMut() {
+    (*f)();
+}
+
+fn test4(f: &Test) {
+    f.f.call_mut(())
+    //~^ ERROR: cannot borrow `f.f` as mutable, as it is behind a `&` reference
+}
+
+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<dyn FnMut(isize)>, isize) {}
+    let s = String::new();  // Capture to make f !Copy
+    let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
+        let _ = s.len();
+    };
+    f(Box::new(|a| {
+        //~^ ERROR cannot move out of `f` because it is borrowed
+        foo(f);
+        //~^ ERROR cannot move out of `f`, a captured variable in an `FnMut` closure
+    }), 3);
+}
+
+fn main() {}
diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr
new file mode 100644
index 00000000000..48b42bc7825
--- /dev/null
+++ b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr
@@ -0,0 +1,61 @@
+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 |     (*f)();
+   |     ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn test2<F>(f: &mut F) where F: FnMut() {
+   |                ~~~~~~
+
+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 |     f.f.call_mut(())
+   |     ^^^^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn test4(f: &mut Test<'_>) {
+   |             ~~~~~~~~~~~~~
+
+error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13
+   |
+LL |     let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
+   |         ----- captured outer variable
+...
+LL |     f(Box::new(|a| {
+   |                --- captured by this `FnMut` closure
+LL |
+LL |         foo(f);
+   |             ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58]`, which does not implement the `Copy` trait
+
+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 |
+LL |         foo(f);
+   |             - move occurs due to use in closure
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0499, E0505, E0507, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/tests/ui/span/borrowck-call-method-from-mut-aliasable.rs b/tests/ui/span/borrowck-call-method-from-mut-aliasable.rs
new file mode 100644
index 00000000000..caf2d2a55fc
--- /dev/null
+++ b/tests/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/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr
new file mode 100644
index 00000000000..2a842f5a2a9
--- /dev/null
+++ b/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr
@@ -0,0 +1,14 @@
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-call-method-from-mut-aliasable.rs:17:5
+   |
+LL |     x.h();
+   |     ^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn b(x: &mut Foo) {
+   |         ~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/span/borrowck-fn-in-const-b.rs b/tests/ui/span/borrowck-fn-in-const-b.rs
new file mode 100644
index 00000000000..822083efee0
--- /dev/null
+++ b/tests/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/tests/ui/span/borrowck-fn-in-const-b.stderr b/tests/ui/span/borrowck-fn-in-const-b.stderr
new file mode 100644
index 00000000000..1df19deb12f
--- /dev/null
+++ b/tests/ui/span/borrowck-fn-in-const-b.stderr
@@ -0,0 +1,14 @@
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-fn-in-const-b.rs:7:9
+   |
+LL |         x.push(format!("this is broken"));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL |     fn broken(x: &mut Vec<String>) {
+   |                  ~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/span/borrowck-let-suggestion-suffixes.rs b/tests/ui/span/borrowck-let-suggestion-suffixes.rs
new file mode 100644
index 00000000000..18abfb5c3fb
--- /dev/null
+++ b/tests/ui/span/borrowck-let-suggestion-suffixes.rs
@@ -0,0 +1,59 @@
+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 `young[_]` dropped here while still borrowed
+
+    let mut v3 = Vec::new(); // statement 5
+
+    v3.push(&id('x'));           // statement 6
+    //~^ ERROR temporary value dropped while borrowed
+    //~| NOTE creates a temporary value which is freed while still in use
+    //~| NOTE temporary value is freed at the end of this statement
+    //~| HELP consider using a `let` binding to create a longer lived value
+
+    {
+
+        let mut v4 = Vec::new(); // (sub) statement 0
+
+        v4.push(&id('y'));
+        //~^ ERROR temporary value dropped while borrowed
+        //~| NOTE creates a temporary value which is freed while still in use
+        //~| NOTE temporary value is freed at the end of this statement
+        //~| NOTE consider using a `let` binding to create a longer lived value
+        v4.use_ref();
+        //~^ NOTE borrow later used here
+    }                       // (statement 7)
+
+    let mut v5 = Vec::new(); // statement 8
+
+    v5.push(&id('z'));
+    //~^ ERROR temporary value dropped while borrowed
+    //~| NOTE creates a temporary value which is freed while still in use
+    //~| NOTE temporary value is freed at the end of this statement
+    //~| HELP consider using a `let` binding to create a longer lived value
+
+    v1.push(&old[0]);
+
+    (v1, v2, v3, /* v4 is above. */ v5).use_ref();
+    //~^ NOTE borrow later used here
+    //~| NOTE borrow later used here
+    //~| NOTE borrow later used here
+}
+
+fn main() {
+    f();
+}
+
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { }  }
+impl<T> Fake for T { }
diff --git a/tests/ui/span/borrowck-let-suggestion-suffixes.stderr b/tests/ui/span/borrowck-let-suggestion-suffixes.stderr
new file mode 100644
index 00000000000..2dc29a78d20
--- /dev/null
+++ b/tests/ui/span/borrowck-let-suggestion-suffixes.stderr
@@ -0,0 +1,63 @@
+error[E0597]: `young[_]` does not live long enough
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:12:17
+   |
+LL |         v2.push(&young[0]);      // statement 4
+   |                 ^^^^^^^^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - `young[_]` dropped here while still borrowed
+...
+LL |     (v1, v2, v3, /* v4 is above. */ v5).use_ref();
+   |          -- borrow later used here
+
+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 value which is freed while still in use
+...
+LL |     (v1, v2, v3, /* v4 is above. */ v5).use_ref();
+   |              -- borrow later used here
+   |
+help: consider using a `let` binding to create a longer lived value
+   |
+LL ~     let binding = id('x');
+LL ~     v3.push(&binding);           // statement 6
+   |
+
+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 value 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 value which is freed while still in use
+...
+LL |     (v1, v2, v3, /* v4 is above. */ v5).use_ref();
+   |                                     -- borrow later used here
+   |
+help: consider using a `let` binding to create a longer lived value
+   |
+LL ~     let binding = id('z');
+LL ~     v5.push(&binding);
+   |
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/tests/ui/span/borrowck-object-mutability.rs b/tests/ui/span/borrowck-object-mutability.rs
new file mode 100644
index 00000000000..f5adc2cc141
--- /dev/null
+++ b/tests/ui/span/borrowck-object-mutability.rs
@@ -0,0 +1,26 @@
+trait Foo {
+    fn borrowed(&self);
+    fn borrowed_mut(&mut self);
+}
+
+fn borrowed_receiver(x: &dyn Foo) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn borrowed_mut_receiver(x: &mut dyn Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn owned_receiver(x: Box<dyn Foo>) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn mut_owned_receiver(mut x: Box<dyn Foo>) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn main() {}
diff --git a/tests/ui/span/borrowck-object-mutability.stderr b/tests/ui/span/borrowck-object-mutability.stderr
new file mode 100644
index 00000000000..b6517e0b309
--- /dev/null
+++ b/tests/ui/span/borrowck-object-mutability.stderr
@@ -0,0 +1,25 @@
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/borrowck-object-mutability.rs:8:5
+   |
+LL |     x.borrowed_mut();
+   |     ^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | fn borrowed_receiver(x: &mut dyn Foo) {
+   |                         ~~~~~~~~~~~~
+
+error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable
+  --> $DIR/borrowck-object-mutability.rs:18:5
+   |
+LL |     x.borrowed_mut();
+   |     ^^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to be mutable
+   |
+LL | fn owned_receiver(mut x: Box<dyn Foo>) {
+   |                   +++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/span/borrowck-ref-into-rvalue.fixed b/tests/ui/span/borrowck-ref-into-rvalue.fixed
new file mode 100644
index 00000000000..51f65e5345d
--- /dev/null
+++ b/tests/ui/span/borrowck-ref-into-rvalue.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+fn main() {
+    let msg;
+    let binding = Some("Hello".to_string());
+    match binding {
+        //~^ ERROR temporary value dropped while borrowed
+        Some(ref m) => {
+            msg = m;
+        },
+        None => { panic!() }
+    }
+    println!("{}", *msg);
+}
diff --git a/tests/ui/span/borrowck-ref-into-rvalue.rs b/tests/ui/span/borrowck-ref-into-rvalue.rs
new file mode 100644
index 00000000000..7b09fad927f
--- /dev/null
+++ b/tests/ui/span/borrowck-ref-into-rvalue.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+fn main() {
+    let msg;
+    match Some("Hello".to_string()) {
+        //~^ ERROR temporary value dropped while borrowed
+        Some(ref m) => {
+            msg = m;
+        },
+        None => { panic!() }
+    }
+    println!("{}", *msg);
+}
diff --git a/tests/ui/span/borrowck-ref-into-rvalue.stderr b/tests/ui/span/borrowck-ref-into-rvalue.stderr
new file mode 100644
index 00000000000..25e344fedfb
--- /dev/null
+++ b/tests/ui/span/borrowck-ref-into-rvalue.stderr
@@ -0,0 +1,20 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/borrowck-ref-into-rvalue.rs:4:11
+   |
+LL |     match Some("Hello".to_string()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value 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
+   |
+help: consider using a `let` binding to create a longer lived value
+   |
+LL ~     let binding = Some("Hello".to_string());
+LL ~     match binding {
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/span/coerce-suggestions.rs b/tests/ui/span/coerce-suggestions.rs
new file mode 100644
index 00000000000..7920ae0b26c
--- /dev/null
+++ b/tests/ui/span/coerce-suggestions.rs
@@ -0,0 +1,23 @@
+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::new(f);
+    //~^ ERROR E0308
+
+    let s = &mut String::new();
+    s = format!("foo");
+    //~^ ERROR E0308
+}
diff --git a/tests/ui/span/coerce-suggestions.stderr b/tests/ui/span/coerce-suggestions.stderr
new file mode 100644
index 00000000000..db784d5fe6c
--- /dev/null
+++ b/tests/ui/span/coerce-suggestions.stderr
@@ -0,0 +1,72 @@
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:7:20
+   |
+LL |     let x: usize = String::new();
+   |            -----   ^^^^^^^^^^^^^ expected `usize`, found struct `String`
+   |            |
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:9:19
+   |
+LL |     let x: &str = String::new();
+   |            ----   ^^^^^^^^^^^^^
+   |            |      |
+   |            |      expected `&str`, found struct `String`
+   |            |      help: consider borrowing here: `&String::new()`
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:12:10
+   |
+LL |     test(&y);
+   |     ---- ^^ types differ in mutability
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected mutable reference `&mut String`
+                      found reference `&String`
+note: function defined here
+  --> $DIR/coerce-suggestions.rs:1:4
+   |
+LL | fn test(_x: &mut String) {}
+   |    ^^^^ ---------------
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:14:11
+   |
+LL |     test2(&y);
+   |     ----- ^^ types differ in mutability
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected mutable reference `&mut i32`
+                      found reference `&String`
+note: function defined here
+  --> $DIR/coerce-suggestions.rs:3:4
+   |
+LL | fn test2(_x: &mut i32) {}
+   |    ^^^^^ ------------
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:17:9
+   |
+LL |     f = Box::new(f);
+   |         ^^^^^^^^^^^ cyclic type of infinite size
+   |
+help: consider unboxing the value
+   |
+LL |     f = *Box::new(f);
+   |         +
+
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestions.rs:21:9
+   |
+LL |     s = format!("foo");
+   |         ^^^^^^^^^^^^^^ expected `&mut String`, found struct `String`
+   |
+   = note: this error originates in the macro `format` (in Nightly builds, run with -Z 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/tests/ui/span/destructor-restrictions.rs b/tests/ui/span/destructor-restrictions.rs
new file mode 100644
index 00000000000..7fb348a14bf
--- /dev/null
+++ b/tests/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/tests/ui/span/destructor-restrictions.stderr b/tests/ui/span/destructor-restrictions.stderr
new file mode 100644
index 00000000000..53c9404620f
--- /dev/null
+++ b/tests/ui/span/destructor-restrictions.stderr
@@ -0,0 +1,23 @@
+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 `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
+help: 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
+   |
+LL |         let x = *a.borrow() + 1; x
+   |         +++++++                +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
new file mode 100644
index 00000000000..4559da91e47
--- /dev/null
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Wrust-2021-incompatible-closure-captures
+
+pub struct A {}
+
+impl A {
+    async fn create(path: impl AsRef<std::path::Path>)  { //~ ERROR  `async fn` is not permitted in Rust 2015
+    //~^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures]
+    ;
+    crate(move || {} ).await //~ ERROR expected function, found module `crate`
+    }
+}
+
+trait C{async fn new(val: T) {} //~ ERROR  `async fn` is not permitted in Rust 2015
+//~^ ERROR functions in traits cannot be declared `async`
+//~| ERROR cannot find type `T` in this scope
+//~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures]
+
+//~ ERROR  this file contains an unclosed delimiter
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
new file mode 100644
index 00000000000..df1cafdb7d3
--- /dev/null
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
@@ -0,0 +1,95 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53
+   |
+LL | trait C{async fn new(val: T) {}
+   |        - unclosed delimiter
+...
+LL |
+   |                                                     ^
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:5
+   |
+LL |     async fn create(path: impl AsRef<std::path::Path>)  {
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9
+   |
+LL | trait C{async fn new(val: T) {}
+   |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0412]: cannot find type `T` in this scope
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:27
+   |
+LL | pub struct A {}
+   | ------------ similarly named struct `A` defined here
+...
+LL | trait C{async fn new(val: T) {}
+   |                           ^ help: a struct with a similar name exists: `A`
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9
+   |
+LL | trait C{async fn new(val: T) {}
+   |         -----^^^^^^^^^^^^^^^
+   |         |
+   |         `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error[E0423]: expected function, found module `crate`
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5
+   |
+LL |     crate(move || {} ).await
+   |     ^^^^^ not a function
+
+warning: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57
+   |
+LL |       async fn create(path: impl AsRef<std::path::Path>)  {
+   |  _____________________----_____________________________-__^
+   | |                     |                                |
+   | |                     |                                in Rust 2018, `path` is dropped here along with the closure, but in Rust 2021 `path` is not part of the closure
+   | |                     in Rust 2018, this causes the closure to capture `path`, but in Rust 2021, it has no effect
+LL | |
+LL | |     ;
+LL | |     crate(move || {} ).await
+LL | |     }
+   | |_____^
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+   = note: requested on the command line with `-W rust-2021-incompatible-closure-captures`
+help: add a dummy let to cause `path` to be fully captured
+   |
+LL |     async fn create(path: impl AsRef<std::path::Path>)  { let _ = &path;
+   |                                                           ++++++++++++++
+
+warning: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30
+   |
+LL | trait C{async fn new(val: T) {}
+   |                      ---   - ^^
+   |                      |     |
+   |                      |     in Rust 2018, `val` is dropped here along with the closure, but in Rust 2021 `val` is not part of the closure
+   |                      in Rust 2018, this causes the closure to capture `val`, but in Rust 2021, it has no effect
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `val` to be fully captured
+   |
+LL | trait C{async fn new(val: T) { let _ = &val;}
+   |                                +++++++++++++
+
+error: aborting due to 6 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0412, E0423, E0670, E0706.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs
new file mode 100644
index 00000000000..a776e508907
--- /dev/null
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs
@@ -0,0 +1,15 @@
+// compile-flags -Wrust-2021-incompatible-closure-captures
+
+fn main() {}
+
+pub(crate) struct Numberer {}
+
+impl Numberer {
+    pub(crate) async fn new(
+    //~^ ERROR `async fn` is not permitted in Rust 2015
+        interval: Duration,
+        //~^ ERROR cannot find type `Duration` in this scope
+    ) -> Numberer {
+        Numberer {}
+    }
+}
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr
new file mode 100644
index 00000000000..37b2f413860
--- /dev/null
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr
@@ -0,0 +1,24 @@
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:8:16
+   |
+LL |     pub(crate) async fn new(
+   |                ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0412]: cannot find type `Duration` in this scope
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:10:19
+   |
+LL |         interval: Duration,
+   |                   ^^^^^^^^ not found in this scope
+   |
+help: consider importing this struct
+   |
+LL | use std::time::Duration;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0412, E0670.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/span/dropck-object-cycle.rs b/tests/ui/span/dropck-object-cycle.rs
new file mode 100644
index 00000000000..a26123d5246
--- /dev/null
+++ b/tests/ui/span/dropck-object-cycle.rs
@@ -0,0 +1,47 @@
+// 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 dyn Trait<'d>) -> (isize, isize) { loop { } }
+
+trait MakerTrait {
+    fn mk() -> Self;
+}
+
+fn make_val<T:MakerTrait>() -> T {
+    MakerTrait::mk()
+}
+
+impl<'t> MakerTrait for Box<dyn Trait<'t>+'static> {
+    fn mk() -> Box<dyn Trait<'t>+'static> { loop { } }
+}
+
+pub fn main() {
+    let m : Box<dyn 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/tests/ui/span/dropck-object-cycle.stderr b/tests/ui/span/dropck-object-cycle.stderr
new file mode 100644
index 00000000000..229d17e1cf9
--- /dev/null
+++ b/tests/ui/span/dropck-object-cycle.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 `Box<dyn Trait<'_>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/span/dropck_arr_cycle_checked.rs b/tests/ui/span/dropck_arr_cycle_checked.rs
new file mode 100644
index 00000000000..a14db5ff089
--- /dev/null
+++ b/tests/ui/span/dropck_arr_cycle_checked.rs
@@ -0,0 +1,106 @@
+// Reject mixing cyclic structure and Drop when using fixed length
+// arrays.
+//
+// (Compare against ui/span/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));
+    b2.a[1].v.set(Some(&b3));
+    b3.a[0].v.set(Some(&b1));
+    //~^ ERROR `b1` does not live long enough
+    b3.a[1].v.set(Some(&b2));
+}
+
+fn main() {
+    f();
+}
diff --git a/tests/ui/span/dropck_arr_cycle_checked.stderr b/tests/ui/span/dropck_arr_cycle_checked.stderr
new file mode 100644
index 00000000000..068c779ae52
--- /dev/null
+++ b/tests/ui/span/dropck_arr_cycle_checked.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:99: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/tests/ui/span/dropck_direct_cycle_with_drop.rs b/tests/ui/span/dropck_direct_cycle_with_drop.rs
new file mode 100644
index 00000000000..14d6e665474
--- /dev/null
+++ b/tests/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/tests/ui/span/dropck_direct_cycle_with_drop.stderr b/tests/ui/span/dropck_direct_cycle_with_drop.stderr
new file mode 100644
index 00000000000..07ae138ac71
--- /dev/null
+++ b/tests/ui/span/dropck_direct_cycle_with_drop.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/tests/ui/span/dropck_misc_variants.rs b/tests/ui/span/dropck_misc_variants.rs
new file mode 100644
index 00000000000..5818a94bcb1
--- /dev/null
+++ b/tests/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/tests/ui/span/dropck_misc_variants.stderr b/tests/ui/span/dropck_misc_variants.stderr
new file mode 100644
index 00000000000..76e90574cef
--- /dev/null
+++ b/tests/ui/span/dropck_misc_variants.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/tests/ui/span/dropck_vec_cycle_checked.rs b/tests/ui/span/dropck_vec_cycle_checked.rs
new file mode 100644
index 00000000000..c5d21507d76
--- /dev/null
+++ b/tests/ui/span/dropck_vec_cycle_checked.rs
@@ -0,0 +1,111 @@
+// Reject mixing cyclic structure and Drop when using Vec.
+//
+// (Compare against ui/span/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));
+    c2.v[1].v.set(Some(&c3));
+    c3.v[0].v.set(Some(&c1));
+    //~^ ERROR `c1` does not live long enough
+    c3.v[1].v.set(Some(&c2));
+}
+
+fn main() {
+    f();
+}
diff --git a/tests/ui/span/dropck_vec_cycle_checked.stderr b/tests/ui/span/dropck_vec_cycle_checked.stderr
new file mode 100644
index 00000000000..7ff991c0c37
--- /dev/null
+++ b/tests/ui/span/dropck_vec_cycle_checked.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:104: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/tests/ui/span/gated-features-attr-spans.rs b/tests/ui/span/gated-features-attr-spans.rs
new file mode 100644
index 00000000000..69511ab8e1f
--- /dev/null
+++ b/tests/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/tests/ui/span/gated-features-attr-spans.stderr b/tests/ui/span/gated-features-attr-spans.stderr
new file mode 100644
index 00000000000..c8b8f346b98
--- /dev/null
+++ b/tests/ui/span/gated-features-attr-spans.stderr
@@ -0,0 +1,12 @@
+error[E0658]: SIMD types are experimental and possibly buggy
+  --> $DIR/gated-features-attr-spans.rs:1:1
+   |
+LL | #[repr(simd)]
+   | ^^^^^^^^^^^^^
+   |
+   = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
+   = 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/tests/ui/span/impl-wrong-item-for-trait.rs b/tests/ui/span/impl-wrong-item-for-trait.rs
new file mode 100644
index 00000000000..bf335868643
--- /dev/null
+++ b/tests/ui/span/impl-wrong-item-for-trait.rs
@@ -0,0 +1,38 @@
+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
+    const MY_CONST: u32 = 1;
+}
+
+impl Debug for FooTypeForMethod {}
+//~^ ERROR E0046
+
+fn main() {}
diff --git a/tests/ui/span/impl-wrong-item-for-trait.stderr b/tests/ui/span/impl-wrong-item-for-trait.stderr
new file mode 100644
index 00000000000..f919092f9ee
--- /dev/null
+++ b/tests/ui/span/impl-wrong-item-for-trait.stderr
@@ -0,0 +1,66 @@
+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[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[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:10:1
+   |
+LL |     fn bar(&self);
+   |     -------------- `bar` from trait
+...
+LL | impl Foo for FooConstForMethod {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bar` in implementation
+
+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[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:35:1
+   |
+LL | impl Debug for FooTypeForMethod {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation
+   |
+   = help: implement the missing item: `fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { todo!() }`
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0046, E0323, E0324, E0325.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/span/import-ty-params.rs b/tests/ui/span/import-ty-params.rs
new file mode 100644
index 00000000000..313cd227b7c
--- /dev/null
+++ b/tests/ui/span/import-ty-params.rs
@@ -0,0 +1,23 @@
+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 f3() {
+    import! { a::b<>::c<u8>::S<> } //~ ERROR unexpected generic arguments in path
+}
+
+fn main() {}
diff --git a/tests/ui/span/import-ty-params.stderr b/tests/ui/span/import-ty-params.stderr
new file mode 100644
index 00000000000..701cd0c04bd
--- /dev/null
+++ b/tests/ui/span/import-ty-params.stderr
@@ -0,0 +1,20 @@
+error: unexpected generic arguments in path
+  --> $DIR/import-ty-params.rs:14:25
+   |
+LL |     import! { a::b::c::S<u8> }
+   |                         ^^^^
+
+error: unexpected generic arguments in path
+  --> $DIR/import-ty-params.rs:17:25
+   |
+LL |     import! { a::b::c::S<> }
+   |                         ^^
+
+error: unexpected generic arguments in path
+  --> $DIR/import-ty-params.rs:20:19
+   |
+LL |     import! { a::b<>::c<u8>::S<> }
+   |                   ^^   ^^^^   ^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/span/issue-11925.rs b/tests/ui/span/issue-11925.rs
new file mode 100644
index 00000000000..cac9fd5bfb6
--- /dev/null
+++ b/tests/ui/span/issue-11925.rs
@@ -0,0 +1,13 @@
+#![feature(unboxed_closures, tuple_trait)]
+
+fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
+
+fn main() {
+    let r = {
+        let x: Box<_> = Box::new(42);
+        let f = to_fn_once(move|| &x); //~ ERROR cannot return reference to local data `x`
+        f()
+    };
+
+    drop(r);
+}
diff --git a/tests/ui/span/issue-11925.stderr b/tests/ui/span/issue-11925.stderr
new file mode 100644
index 00000000000..1d317fc331f
--- /dev/null
+++ b/tests/ui/span/issue-11925.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/tests/ui/span/issue-15480.fixed b/tests/ui/span/issue-15480.fixed
new file mode 100644
index 00000000000..e6d1a4dd328
--- /dev/null
+++ b/tests/ui/span/issue-15480.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let binding = id(3);
+    let v = vec![
+        &binding
+    ];
+    //~^^ ERROR temporary value dropped while borrowed
+
+    for &&x in &v {
+        println!("{}", x + 3);
+    }
+}
diff --git a/tests/ui/span/issue-15480.rs b/tests/ui/span/issue-15480.rs
new file mode 100644
index 00000000000..916ce4b1edb
--- /dev/null
+++ b/tests/ui/span/issue-15480.rs
@@ -0,0 +1,13 @@
+// run-rustfix
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let v = vec![
+        &id(3)
+    ];
+    //~^^ ERROR temporary value dropped while borrowed
+
+    for &&x in &v {
+        println!("{}", x + 3);
+    }
+}
diff --git a/tests/ui/span/issue-15480.stderr b/tests/ui/span/issue-15480.stderr
new file mode 100644
index 00000000000..d9cce2254dd
--- /dev/null
+++ b/tests/ui/span/issue-15480.stderr
@@ -0,0 +1,21 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-15480.rs:6:10
+   |
+LL |         &id(3)
+   |          ^^^^^ creates a temporary value 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
+   |
+help: consider using a `let` binding to create a longer lived value
+   |
+LL ~     let binding = id(3);
+LL ~     let v = vec![
+LL ~         &binding
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs
new file mode 100644
index 00000000000..a92ea4ddc96
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
new file mode 100644
index 00000000000..3c2022748f0
--- /dev/null
+++ b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
@@ -0,0 +1,44 @@
+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 `Ref<'_, 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
+help: 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
+   |
+LL |     let x = y.borrow().clone(); x
+   |     +++++++                   +++
+
+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 `Ref<'_, 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
+help: 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
+   |
+LL |         let x = y.borrow().clone(); x
+   |         +++++++                   +++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/span/issue-23729.rs b/tests/ui/span/issue-23729.rs
new file mode 100644
index 00000000000..ca33f9c7730
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-23729.stderr b/tests/ui/span/issue-23729.stderr
new file mode 100644
index 00000000000..f88ce6c88db
--- /dev/null
+++ b/tests/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
+   |
+   = help: implement the missing item: `type Item = Type;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/span/issue-23827.rs b/tests/ui/span/issue-23827.rs
new file mode 100644
index 00000000000..6b065bf6cbf
--- /dev/null
+++ b/tests/ui/span/issue-23827.rs
@@ -0,0 +1,33 @@
+// Regression test for #23827
+
+#![feature(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/tests/ui/span/issue-23827.stderr b/tests/ui/span/issue-23827.stderr
new file mode 100644
index 00000000000..46a820f1b76
--- /dev/null
+++ b/tests/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
+   |
+   = help: implement the missing item: `type Output = Type;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/span/issue-24356.rs b/tests/ui/span/issue-24356.rs
new file mode 100644
index 00000000000..7ec05aab29a
--- /dev/null
+++ b/tests/ui/span/issue-24356.rs
@@ -0,0 +1,27 @@
+// Regression test for #24356
+
+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/tests/ui/span/issue-24356.stderr b/tests/ui/span/issue-24356.stderr
new file mode 100644
index 00000000000..a1f9b255020
--- /dev/null
+++ b/tests/ui/span/issue-24356.stderr
@@ -0,0 +1,11 @@
+error[E0046]: not all trait items implemented, missing: `Target`
+  --> $DIR/issue-24356.rs:18:9
+   |
+LL |         impl Deref for Thing {
+   |         ^^^^^^^^^^^^^^^^^^^^ missing `Target` in implementation
+   |
+   = help: implement the missing item: `type Target = Type;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/span/issue-24690.rs b/tests/ui/span/issue-24690.rs
new file mode 100644
index 00000000000..2b7349c5503
--- /dev/null
+++ b/tests/ui/span/issue-24690.rs
@@ -0,0 +1,16 @@
+//! A test to ensure that helpful `note` messages aren't emitted more often
+//! than necessary.
+
+// check-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/tests/ui/span/issue-24690.stderr b/tests/ui/span/issue-24690.stderr
new file mode 100644
index 00000000000..73e166e6403
--- /dev/null
+++ b/tests/ui/span/issue-24690.stderr
@@ -0,0 +1,29 @@
+warning: unused variable: `theOtherTwo`
+  --> $DIR/issue-24690.rs:13:9
+   |
+LL |     let theOtherTwo = 2;
+   |         ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_theOtherTwo`
+   |
+note: the lint level is 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`
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs
new file mode 100644
index 00000000000..9c772052fb4
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
new file mode 100644
index 00000000000..809e60a8c8a
--- /dev/null
+++ b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.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/tests/ui/span/issue-24805-dropck-trait-has-items.rs b/tests/ui/span/issue-24805-dropck-trait-has-items.rs
new file mode 100644
index 00000000000..b5c410cd3c9
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-24805-dropck-trait-has-items.stderr b/tests/ui/span/issue-24805-dropck-trait-has-items.stderr
new file mode 100644
index 00000000000..2e217066915
--- /dev/null
+++ b/tests/ui/span/issue-24805-dropck-trait-has-items.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/tests/ui/span/issue-24895-copy-clone-dropck.rs b/tests/ui/span/issue-24895-copy-clone-dropck.rs
new file mode 100644
index 00000000000..904cd8f678f
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-24895-copy-clone-dropck.stderr b/tests/ui/span/issue-24895-copy-clone-dropck.stderr
new file mode 100644
index 00000000000..18a3dc9e6de
--- /dev/null
+++ b/tests/ui/span/issue-24895-copy-clone-dropck.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/tests/ui/span/issue-25199.rs b/tests/ui/span/issue-25199.rs
new file mode 100644
index 00000000000..dbc3b190068
--- /dev/null
+++ b/tests/ui/span/issue-25199.rs
@@ -0,0 +1,74 @@
+// 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<dyn 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);
+}
diff --git a/tests/ui/span/issue-25199.stderr b/tests/ui/span/issue-25199.stderr
new file mode 100644
index 00000000000..d70a4afc1bf
--- /dev/null
+++ b/tests/ui/span/issue-25199.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/tests/ui/span/issue-26656.rs b/tests/ui/span/issue-26656.rs
new file mode 100644
index 00000000000..cde68da1897
--- /dev/null
+++ b/tests/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<dyn 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/tests/ui/span/issue-26656.stderr b/tests/ui/span/issue-26656.stderr
new file mode 100644
index 00000000000..1e939c484fb
--- /dev/null
+++ b/tests/ui/span/issue-26656.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/tests/ui/span/issue-27522.rs b/tests/ui/span/issue-27522.rs
new file mode 100644
index 00000000000..7a0cfb679ed
--- /dev/null
+++ b/tests/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 `self` parameter type
+}
+
+fn main() {}
diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr
new file mode 100644
index 00000000000..8a254a96855
--- /dev/null
+++ b/tests/ui/span/issue-27522.stderr
@@ -0,0 +1,12 @@
+error[E0307]: invalid `self` parameter type: &SomeType
+  --> $DIR/issue-27522.rs:6:22
+   |
+LL |     fn handler(self: &SomeType);
+   |                      ^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/span/issue-29106.rs b/tests/ui/span/issue-29106.rs
new file mode 100644
index 00000000000..1be8d4cba69
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-29106.stderr b/tests/ui/span/issue-29106.stderr
new file mode 100644
index 00000000000..71fbd60ee73
--- /dev/null
+++ b/tests/ui/span/issue-29106.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 `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 `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/tests/ui/span/issue-29595.rs b/tests/ui/span/issue-29595.rs
new file mode 100644
index 00000000000..87d7c4cfdf9
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-29595.stderr b/tests/ui/span/issue-29595.stderr
new file mode 100644
index 00000000000..92445e40731
--- /dev/null
+++ b/tests/ui/span/issue-29595.stderr
@@ -0,0 +1,9 @@
+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`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/span/issue-33884.rs b/tests/ui/span/issue-33884.rs
new file mode 100644
index 00000000000..5d927a5acc8
--- /dev/null
+++ b/tests/ui/span/issue-33884.rs
@@ -0,0 +1,18 @@
+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/tests/ui/span/issue-33884.stderr b/tests/ui/span/issue-33884.stderr
new file mode 100644
index 00000000000..aee15308517
--- /dev/null
+++ b/tests/ui/span/issue-33884.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-33884.rs:6:22
+   |
+LL |     stream.write_fmt(format!("message received"))
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Arguments`, found struct `String`
+   |
+   = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/span/issue-34264.rs b/tests/ui/span/issue-34264.rs
new file mode 100644
index 00000000000..9227ee482df
--- /dev/null
+++ b/tests/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 function takes
+    bar("", ""); //~ ERROR mismatched types
+    bar(1, 2);
+    bar(1, 2, 3); //~ ERROR function takes
+}
diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr
new file mode 100644
index 00000000000..15179954adc
--- /dev/null
+++ b/tests/ui/span/issue-34264.stderr
@@ -0,0 +1,102 @@
+error: expected one of `:`, `@`, or `|`, found `<`
+  --> $DIR/issue-34264.rs:1:14
+   |
+LL | fn foo(Option<i32>, String) {}
+   |              ^ expected one of `:`, `@`, or `|`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this is a `self` type, give it a parameter name
+   |
+LL | fn foo(self: Option<i32>, String) {}
+   |        +++++
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL | fn foo(_: Option<i32>, String) {}
+   |        ++
+
+error: expected one of `:`, `@`, or `|`, found `)`
+  --> $DIR/issue-34264.rs:1:27
+   |
+LL | fn foo(Option<i32>, String) {}
+   |                           ^ expected one of `:`, `@`, or `|`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this is a parameter name, give it a type
+   |
+LL | fn foo(Option<i32>, String: TypeName) {}
+   |                           ++++++++++
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL | fn foo(Option<i32>, _: String) {}
+   |                     ++
+
+error: expected one of `:`, `@`, or `|`, found `,`
+  --> $DIR/issue-34264.rs:3:9
+   |
+LL | fn bar(x, y: usize) {}
+   |         ^ expected one of `:`, `@`, or `|`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this is a `self` type, give it a parameter name
+   |
+LL | fn bar(self: x, y: usize) {}
+   |        +++++
+help: if this is a parameter name, give it a type
+   |
+LL | fn bar(x: TypeName, y: usize) {}
+   |         ++++++++++
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL | fn bar(_: x, y: usize) {}
+   |        ++
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/issue-34264.rs:7:5
+   |
+LL |     foo(Some(42), 2, "");
+   |     ^^^              -- argument of type `&'static str` unexpected
+   |
+note: function defined here
+  --> $DIR/issue-34264.rs:1:4
+   |
+LL | fn foo(Option<i32>, String) {}
+   |    ^^^ -----------  ------
+help: remove the extra argument
+   |
+LL |     foo(Some(42), 2);
+   |        ~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/issue-34264.rs:8:13
+   |
+LL |     bar("", "");
+   |     ---     ^^ expected `usize`, found `&str`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/issue-34264.rs:3:4
+   |
+LL | fn bar(x, y: usize) {}
+   |    ^^^    --------
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+  --> $DIR/issue-34264.rs:10:5
+   |
+LL |     bar(1, 2, 3);
+   |     ^^^       - argument of type `{integer}` unexpected
+   |
+note: function defined here
+  --> $DIR/issue-34264.rs:3:4
+   |
+LL | fn bar(x, y: usize) {}
+   |    ^^^ -  --------
+help: remove the extra argument
+   |
+LL |     bar(1, 2);
+   |        ~~~~~~
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/span/issue-35987.rs b/tests/ui/span/issue-35987.rs
new file mode 100644
index 00000000000..3a6e6ffe249
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-35987.stderr b/tests/ui/span/issue-35987.stderr
new file mode 100644
index 00000000000..057d40ac0cb
--- /dev/null
+++ b/tests/ui/span/issue-35987.stderr
@@ -0,0 +1,19 @@
+error[E0404]: expected trait, found type parameter `Add`
+  --> $DIR/issue-35987.rs:5:21
+   |
+LL | use std::ops::Add;
+   |               --- you might have meant to refer to this trait
+LL |
+LL | impl<T: Clone, Add> Add for Foo<T> {
+   |                ---  ^^^ not a trait
+   |                |
+   |                found this type parameter
+   |
+help: consider importing this trait instead
+   |
+LL | use std::ops::Add;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/span/issue-36537.rs b/tests/ui/span/issue-36537.rs
new file mode 100644
index 00000000000..a5546ccbb60
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-36537.stderr b/tests/ui/span/issue-36537.stderr
new file mode 100644
index 00000000000..79a0ebaeb8d
--- /dev/null
+++ b/tests/ui/span/issue-36537.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-36537.rs:5:13
+   |
+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/tests/ui/span/issue-37767.rs b/tests/ui/span/issue-37767.rs
new file mode 100644
index 00000000000..9e34c2c1fac
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr
new file mode 100644
index 00000000000..f7732847a28
--- /dev/null
+++ b/tests/ui/span/issue-37767.stderr
@@ -0,0 +1,78 @@
+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) {}
+   |     ^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in the trait `B`
+  --> $DIR/issue-37767.rs:6:5
+   |
+LL |     fn foo(&mut self) {}
+   |     ^^^^^^^^^^^^^^^^^
+help: disambiguate the associated function for candidate #1
+   |
+LL |     A::foo(&a)
+   |     ~~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+   |
+LL |     B::foo(&a)
+   |     ~~~~~~~~~~
+
+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) {}
+   |     ^^^^^^^^^^^^^
+note: candidate #2 is defined in the trait `D`
+  --> $DIR/issue-37767.rs:18:5
+   |
+LL |     fn foo(&self) {}
+   |     ^^^^^^^^^^^^^
+help: disambiguate the associated function for candidate #1
+   |
+LL |     C::foo(&a)
+   |     ~~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+   |
+LL |     D::foo(&a)
+   |     ~~~~~~~~~~
+
+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) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in the trait `F`
+  --> $DIR/issue-37767.rs:30:5
+   |
+LL |     fn foo(self) {}
+   |     ^^^^^^^^^^^^
+help: disambiguate the associated function for candidate #1
+   |
+LL |     E::foo(a)
+   |     ~~~~~~~~~
+help: disambiguate the associated function for candidate #2
+   |
+LL |     F::foo(a)
+   |     ~~~~~~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/span/issue-39018.rs b/tests/ui/span/issue-39018.rs
new file mode 100644
index 00000000000..b6db4008db0
--- /dev/null
+++ b/tests/ui/span/issue-39018.rs
@@ -0,0 +1,38 @@
+pub fn main() {
+    let x = "Hello " + "World!";
+    //~^ ERROR cannot add
+
+    // 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 add
+
+    let x = "Hello " + "World!".to_owned();
+    //~^ ERROR cannot add
+}
+
+enum World {
+    Hello,
+    Goodbye,
+}
+
+fn foo() {
+    let a = String::new();
+    let b = String::new();
+    let c = "";
+    let d = "";
+    let e = &a;
+    let _ = &a + &b; //~ ERROR cannot add
+    let _ = &a + b; //~ ERROR cannot add
+    let _ = a + &b; // ok
+    let _ = a + b; //~ ERROR mismatched types
+    let _ = e + b; //~ ERROR cannot add
+    let _ = e + &b; //~ ERROR cannot add
+    let _ = e + d; //~ ERROR cannot add
+    let _ = e + &d; //~ ERROR cannot add
+    let _ = &c + &d; //~ ERROR cannot add
+    let _ = &c + d; //~ ERROR cannot add
+    let _ = c + &d; //~ ERROR cannot add
+    let _ = c + d; //~ ERROR cannot add
+}
diff --git a/tests/ui/span/issue-39018.stderr b/tests/ui/span/issue-39018.stderr
new file mode 100644
index 00000000000..5d4d692b2cf
--- /dev/null
+++ b/tests/ui/span/issue-39018.stderr
@@ -0,0 +1,194 @@
+error[E0369]: cannot add `&str` to `&str`
+  --> $DIR/issue-39018.rs:2:22
+   |
+LL |     let x = "Hello " + "World!";
+   |             -------- ^ -------- &str
+   |             |        |
+   |             |        `+` cannot be used to concatenate two `&str` strings
+   |             &str
+   |
+   = note: string concatenation requires an owned `String` on the left
+help: create an owned `String` from a string reference
+   |
+LL |     let x = "Hello ".to_owned() + "World!";
+   |                     +++++++++++
+
+error[E0369]: cannot add `World` to `World`
+  --> $DIR/issue-39018.rs:8:26
+   |
+LL |     let y = World::Hello + World::Goodbye;
+   |             ------------ ^ -------------- World
+   |             |
+   |             World
+   |
+note: an implementation of `Add<_>` might be missing for `World`
+  --> $DIR/issue-39018.rs:15:1
+   |
+LL | enum World {
+   | ^^^^^^^^^^ must implement `Add<_>`
+note: the trait `Add` must be implemented
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+
+error[E0369]: cannot add `String` to `&str`
+  --> $DIR/issue-39018.rs:11:22
+   |
+LL |     let x = "Hello " + "World!".to_owned();
+   |             -------- ^ ------------------- String
+   |             |        |
+   |             |        `+` cannot be used to concatenate a `&str` with a `String`
+   |             &str
+   |
+help: create an owned `String` on the left and add a borrow on the right
+   |
+LL |     let x = "Hello ".to_owned() + &"World!".to_owned();
+   |                     +++++++++++   +
+
+error[E0369]: cannot add `&String` to `&String`
+  --> $DIR/issue-39018.rs:26:16
+   |
+LL |     let _ = &a + &b;
+   |             -- ^ -- &String
+   |             |  |
+   |             |  `+` cannot be used to concatenate two `&str` strings
+   |             &String
+   |
+   = note: string concatenation requires an owned `String` on the left
+help: remove the borrow to obtain an owned `String`
+   |
+LL -     let _ = &a + &b;
+LL +     let _ = a + &b;
+   |
+
+error[E0369]: cannot add `String` to `&String`
+  --> $DIR/issue-39018.rs:27:16
+   |
+LL |     let _ = &a + b;
+   |             -- ^ - String
+   |             |  |
+   |             |  `+` cannot be used to concatenate a `&str` with a `String`
+   |             &String
+   |
+help: remove the borrow on the left and add one on the right
+   |
+LL -     let _ = &a + b;
+LL +     let _ = a + &b;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/issue-39018.rs:29:17
+   |
+LL |     let _ = a + b;
+   |                 ^
+   |                 |
+   |                 expected `&str`, found struct `String`
+   |                 help: consider borrowing here: `&b`
+
+error[E0369]: cannot add `String` to `&String`
+  --> $DIR/issue-39018.rs:30:15
+   |
+LL |     let _ = e + b;
+   |             - ^ - String
+   |             | |
+   |             | `+` cannot be used to concatenate a `&str` with a `String`
+   |             &String
+   |
+help: create an owned `String` on the left and add a borrow on the right
+   |
+LL |     let _ = e.to_owned() + &b;
+   |              +++++++++++   +
+
+error[E0369]: cannot add `&String` to `&String`
+  --> $DIR/issue-39018.rs:31:15
+   |
+LL |     let _ = e + &b;
+   |             - ^ -- &String
+   |             | |
+   |             | `+` cannot be used to concatenate two `&str` strings
+   |             &String
+   |
+   = note: string concatenation requires an owned `String` on the left
+help: create an owned `String` from a string reference
+   |
+LL |     let _ = e.to_owned() + &b;
+   |              +++++++++++
+
+error[E0369]: cannot add `&str` to `&String`
+  --> $DIR/issue-39018.rs:32:15
+   |
+LL |     let _ = e + d;
+   |             - ^ - &str
+   |             | |
+   |             | `+` cannot be used to concatenate two `&str` strings
+   |             &String
+   |
+   = note: string concatenation requires an owned `String` on the left
+help: create an owned `String` from a string reference
+   |
+LL |     let _ = e.to_owned() + d;
+   |              +++++++++++
+
+error[E0369]: cannot add `&&str` to `&String`
+  --> $DIR/issue-39018.rs:33:15
+   |
+LL |     let _ = e + &d;
+   |             - ^ -- &&str
+   |             | |
+   |             | `+` cannot be used to concatenate two `&str` strings
+   |             &String
+   |
+   = note: string concatenation requires an owned `String` on the left
+help: create an owned `String` from a string reference
+   |
+LL |     let _ = e.to_owned() + &d;
+   |              +++++++++++
+
+error[E0369]: cannot add `&&str` to `&&str`
+  --> $DIR/issue-39018.rs:34:16
+   |
+LL |     let _ = &c + &d;
+   |             -- ^ -- &&str
+   |             |
+   |             &&str
+
+error[E0369]: cannot add `&str` to `&&str`
+  --> $DIR/issue-39018.rs:35:16
+   |
+LL |     let _ = &c + d;
+   |             -- ^ - &str
+   |             |
+   |             &&str
+
+error[E0369]: cannot add `&&str` to `&str`
+  --> $DIR/issue-39018.rs:36:15
+   |
+LL |     let _ = c + &d;
+   |             - ^ -- &&str
+   |             | |
+   |             | `+` cannot be used to concatenate two `&str` strings
+   |             &str
+   |
+   = note: string concatenation requires an owned `String` on the left
+help: create an owned `String` from a string reference
+   |
+LL |     let _ = c.to_owned() + &d;
+   |              +++++++++++
+
+error[E0369]: cannot add `&str` to `&str`
+  --> $DIR/issue-39018.rs:37:15
+   |
+LL |     let _ = c + d;
+   |             - ^ - &str
+   |             | |
+   |             | `+` cannot be used to concatenate two `&str` strings
+   |             &str
+   |
+   = note: string concatenation requires an owned `String` on the left
+help: create an owned `String` from a string reference
+   |
+LL |     let _ = c.to_owned() + d;
+   |              +++++++++++
+
+error: aborting due to 14 previous errors
+
+Some errors have detailed explanations: E0308, E0369.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/span/issue-39698.rs b/tests/ui/span/issue-39698.rs
new file mode 100644
index 00000000000..1079bae2c06
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr
new file mode 100644
index 00000000000..25c35fd5479
--- /dev/null
+++ b/tests/ui/span/issue-39698.stderr
@@ -0,0 +1,43 @@
+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 `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 `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/tests/ui/span/issue-40157.rs b/tests/ui/span/issue-40157.rs
new file mode 100644
index 00000000000..03ad21ae773
--- /dev/null
+++ b/tests/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/tests/ui/span/issue-40157.stderr b/tests/ui/span/issue-40157.stderr
new file mode 100644
index 00000000000..57f80214a4f
--- /dev/null
+++ b/tests/ui/span/issue-40157.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/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr
new file mode 100644
index 00000000000..2b178990850
--- /dev/null
+++ b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr
@@ -0,0 +1,27 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-42234-unknown-receiver-type.rs:9:24
+   |
+LL |     let x: Option<_> = None;
+   |                        ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
+LL |     x.unwrap().method_that_could_exist_on_some_type();
+   |     ---------- type must be known at this point
+   |
+help: consider specifying the generic argument
+   |
+LL |     let x: Option<_> = None::<T>;
+   |                            +++++
+
+error[E0282]: type annotations needed
+  --> $DIR/issue-42234-unknown-receiver-type.rs:15:10
+   |
+LL |         .sum::<_>()
+   |          ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
+   |
+help: consider specifying the generic argument
+   |
+LL |         .sum::<_>()
+   |             ~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr
new file mode 100644
index 00000000000..d93d54e878b
--- /dev/null
+++ b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr
@@ -0,0 +1,27 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-42234-unknown-receiver-type.rs:9:24
+   |
+LL |     let x: Option<_> = None;
+   |                        ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
+LL |     x.unwrap().method_that_could_exist_on_some_type();
+   |     ---------- type must be known at this point
+   |
+help: consider specifying the generic argument
+   |
+LL |     let x: Option<_> = None::<T>;
+   |                            +++++
+
+error[E0282]: type annotations needed
+  --> $DIR/issue-42234-unknown-receiver-type.rs:15:10
+   |
+LL |         .sum::<_>()
+   |          ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
+   |
+help: consider specifying the generic argument
+   |
+LL |         .sum::<S>()
+   |             ~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.rs b/tests/ui/span/issue-42234-unknown-receiver-type.rs
new file mode 100644
index 00000000000..fd53121204c
--- /dev/null
+++ b/tests/ui/span/issue-42234-unknown-receiver-type.rs
@@ -0,0 +1,19 @@
+// revisions: full generic_arg
+#![cfg_attr(generic_arg, feature(generic_arg_infer))]
+
+// 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; //~ ERROR type annotations needed
+    x.unwrap().method_that_could_exist_on_some_type();
+}
+
+fn courier_to_des_moines_and_points_west(data: &[u32]) -> String {
+    data.iter()
+        .sum::<_>() //~ ERROR type annotations needed
+        .to_string()
+}
+
+fn main() {}
diff --git a/tests/ui/span/issue-43927-non-ADT-derive.rs b/tests/ui/span/issue-43927-non-ADT-derive.rs
new file mode 100644
index 00000000000..935bfa001bf
--- /dev/null
+++ b/tests/ui/span/issue-43927-non-ADT-derive.rs
@@ -0,0 +1,6 @@
+#![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+//~^ ERROR cannot determine resolution for the attribute macro `derive`
+//~^^ ERROR `derive` attribute cannot be used at crate level
+struct DerivedOn;
+
+fn main() {}
diff --git a/tests/ui/span/issue-43927-non-ADT-derive.stderr b/tests/ui/span/issue-43927-non-ADT-derive.stderr
new file mode 100644
index 00000000000..e3ae37e3689
--- /dev/null
+++ b/tests/ui/span/issue-43927-non-ADT-derive.stderr
@@ -0,0 +1,21 @@
+error: cannot determine resolution for the attribute macro `derive`
+  --> $DIR/issue-43927-non-ADT-derive.rs:1:4
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |    ^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: `derive` attribute cannot be used at crate level
+  --> $DIR/issue-43927-non-ADT-derive.rs:1:1
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/span/issue-71363.rs b/tests/ui/span/issue-71363.rs
new file mode 100644
index 00000000000..8014f379625
--- /dev/null
+++ b/tests/ui/span/issue-71363.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Z ui-testing=no
+
+struct MyError;
+impl std::error::Error for MyError {}
+//~^ ERROR: `MyError` doesn't implement `std::fmt::Display`
+//~| ERROR: `MyError` doesn't implement `Debug`
+
+fn main() {}
+
+// This test relies on library/std/src/error.rs *not* being included in the error message, so that
+// we can test whether a file not included in the error message affects it (more specifically
+// whether the line number of the excluded file affects the indentation of the other line numbers).
+//
+// To test this we're simulating a remap of the rust src base (so that library/std/src/error.rs
+// does not point to a local file) *and* we're disabling the code to try mapping a remapped path to
+// a local file (which would defeat the purpose of the former flag).
+//
+// Note that this comment is at the bottom of the file intentionally, as we need the line number of
+// the impl to be lower than 10.
diff --git a/tests/ui/span/issue-71363.stderr b/tests/ui/span/issue-71363.stderr
new file mode 100644
index 00000000000..6c7ea007ee0
--- /dev/null
+++ b/tests/ui/span/issue-71363.stderr
@@ -0,0 +1,29 @@
+error[E0277]: `MyError` doesn't implement `std::fmt::Display`
+ --> $DIR/issue-71363.rs:4:6
+  |
+4 | impl std::error::Error for MyError {}
+  |      ^^^^^^^^^^^^^^^^^ `MyError` cannot be formatted with the default formatter
+  |
+  = help: the trait `std::fmt::Display` is not implemented for `MyError`
+  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `std::error::Error`
+ --> $SRC_DIR/core/src/error.rs:LL:COL
+
+error[E0277]: `MyError` doesn't implement `Debug`
+ --> $DIR/issue-71363.rs:4:6
+  |
+4 | impl std::error::Error for MyError {}
+  |      ^^^^^^^^^^^^^^^^^ `MyError` cannot be formatted using `{:?}`
+  |
+  = help: the trait `Debug` is not implemented for `MyError`
+  = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError`
+note: required by a bound in `std::error::Error`
+ --> $SRC_DIR/core/src/error.rs:LL:COL
+help: consider annotating `MyError` with `#[derive(Debug)]`
+  |
+3 | #[derive(Debug)]
+  |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/span/issue-81800.rs b/tests/ui/span/issue-81800.rs
new file mode 100644
index 00000000000..6ac66fdcb65
--- /dev/null
+++ b/tests/ui/span/issue-81800.rs
@@ -0,0 +1,2 @@
+fn x˂- //~ ERROR: unknown start of token
+       //~^ ERROR: expected one of `#`, `>`, `const`, identifier, or lifetime, found `-`
diff --git a/tests/ui/span/issue-81800.stderr b/tests/ui/span/issue-81800.stderr
new file mode 100644
index 00000000000..86c64573b14
--- /dev/null
+++ b/tests/ui/span/issue-81800.stderr
@@ -0,0 +1,19 @@
+error: unknown start of token: \u{2c2}
+  --> $DIR/issue-81800.rs:1:5
+   |
+LL | fn x˂-
+   |     ^
+   |
+help: Unicode character '˂' (Modifier Letter Left Arrowhead) looks like '<' (Less-Than Sign), but it is not
+   |
+LL | fn x<-
+   |     ~
+
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `-`
+  --> $DIR/issue-81800.rs:1:6
+   |
+LL | fn x˂-
+   |      ^ expected one of `#`, `>`, `const`, identifier, or lifetime
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/span/issue28498-reject-ex1.rs b/tests/ui/span/issue28498-reject-ex1.rs
new file mode 100644
index 00000000000..4d1b4125503
--- /dev/null
+++ b/tests/ui/span/issue28498-reject-ex1.rs
@@ -0,0 +1,37 @@
+// 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 borrow may still be in use when destructor runs
+    foo.data[1].1.set(Some(&foo.data[0]));
+}
diff --git a/tests/ui/span/issue28498-reject-ex1.stderr b/tests/ui/span/issue28498-reject-ex1.stderr
new file mode 100644
index 00000000000..86e2d8c56b0
--- /dev/null
+++ b/tests/ui/span/issue28498-reject-ex1.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/tests/ui/span/issue28498-reject-lifetime-param.rs b/tests/ui/span/issue28498-reject-lifetime-param.rs
new file mode 100644
index 00000000000..1e719015785
--- /dev/null
+++ b/tests/ui/span/issue28498-reject-lifetime-param.rs
@@ -0,0 +1,36 @@
+// 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 `may_dangle` 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); // OK
+    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/tests/ui/span/issue28498-reject-lifetime-param.stderr b/tests/ui/span/issue28498-reject-lifetime-param.stderr
new file mode 100644
index 00000000000..3119ddd03cc
--- /dev/null
+++ b/tests/ui/span/issue28498-reject-lifetime-param.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-lifetime-param.rs:32: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/tests/ui/span/issue28498-reject-passed-to-fn.rs b/tests/ui/span/issue28498-reject-passed-to-fn.rs
new file mode 100644
index 00000000000..dcd2e9ad4ba
--- /dev/null
+++ b/tests/ui/span/issue28498-reject-passed-to-fn.rs
@@ -0,0 +1,38 @@
+// 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 `may_dangle` 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)); // OK
+    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/tests/ui/span/issue28498-reject-passed-to-fn.stderr b/tests/ui/span/issue28498-reject-passed-to-fn.stderr
new file mode 100644
index 00000000000..60e8a648cd5
--- /dev/null
+++ b/tests/ui/span/issue28498-reject-passed-to-fn.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-passed-to-fn.rs:34: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/tests/ui/span/issue28498-reject-trait-bound.rs b/tests/ui/span/issue28498-reject-trait-bound.rs
new file mode 100644
index 00000000000..444cebb19a7
--- /dev/null
+++ b/tests/ui/span/issue28498-reject-trait-bound.rs
@@ -0,0 +1,38 @@
+// 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 `may_dangle` 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); // OK
+    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/tests/ui/span/issue28498-reject-trait-bound.stderr b/tests/ui/span/issue28498-reject-trait-bound.stderr
new file mode 100644
index 00000000000..22e4a8205b6
--- /dev/null
+++ b/tests/ui/span/issue28498-reject-trait-bound.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-trait-bound.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/tests/ui/span/lint-unused-unsafe-thir.rs b/tests/ui/span/lint-unused-unsafe-thir.rs
new file mode 100644
index 00000000000..adb72c26bba
--- /dev/null
+++ b/tests/ui/span/lint-unused-unsafe-thir.rs
@@ -0,0 +1,61 @@
+// FIXME: This file is tracking old lint behavior that's still unchanged in the
+// unstable -Zthir-unsafeck implementation. See lint-unused-unsafe.rs for more details.
+//
+// Exercise the unused_unsafe attribute in some positive and negative cases
+
+// compile-flags: -Zthir-unsafeck
+
+#![allow(dead_code)]
+#![deny(unused_unsafe)]
+
+
+mod foo {
+    extern "C" {
+        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() } }
+fn bad6() {
+    unsafe {                             // don't put the warning here
+        unsafe {                         //~ ERROR: unnecessary `unsafe` block
+            unsf()
+        }
+    }
+}
+unsafe fn bad7() {
+    unsafe {
+        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/tests/ui/span/lint-unused-unsafe-thir.stderr b/tests/ui/span/lint-unused-unsafe-thir.stderr
new file mode 100644
index 00000000000..3bcbb759775
--- /dev/null
+++ b/tests/ui/span/lint-unused-unsafe-thir.stderr
@@ -0,0 +1,50 @@
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe-thir.rs:21:13
+   |
+LL | fn bad1() { unsafe {} }
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe-thir.rs:9:9
+   |
+LL | #![deny(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe-thir.rs:22:13
+   |
+LL | fn bad2() { unsafe { bad1() } }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe-thir.rs:23: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-thir.rs:24:13
+   |
+LL | fn bad4() { unsafe { callback(||{}) } }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe-thir.rs:28: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-thir.rs:35:9
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/span/lint-unused-unsafe.mir.stderr b/tests/ui/span/lint-unused-unsafe.mir.stderr
new file mode 100644
index 00000000000..d8412908c73
--- /dev/null
+++ b/tests/ui/span/lint-unused-unsafe.mir.stderr
@@ -0,0 +1,1402 @@
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:26:13
+   |
+LL | fn bad1() { unsafe {} }
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:14:9
+   |
+LL | #![deny(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:27:13
+   |
+LL | fn bad2() { unsafe { bad1() } }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:28:20
+   |
+LL | unsafe fn bad3() { unsafe {} }
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:29:13
+   |
+LL | fn bad4() { unsafe { callback(||{}) } }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:32:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:39:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:74:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:83:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:84:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:85:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:90:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:100:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+LL |             unsf();
+LL |             unsafe { unsf() }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:101:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |             unsafe { unsf() }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:102:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |             unsafe { unsf() }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:112:17
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |                 unsafe { unsf() }
+   |                 ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:110:20
+   |
+LL |             #[deny(unused_unsafe)]
+   |                    ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:113:17
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |                 unsafe { unsf() }
+   |                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:114:17
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |                 unsafe { unsf() }
+   |                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:124:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:134:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:135:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:136:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:142:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:153:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+LL |             unsf();
+LL |             unsafe { unsf() }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:154:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |             unsafe { unsf() }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:155:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |             unsafe { unsf() }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:166:17
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |                 unsafe { unsf() }
+   |                 ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:164:20
+   |
+LL |             #[deny(unused_unsafe)]
+   |                    ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:167:17
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |                 unsafe { unsf() }
+   |                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:168:17
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |                 unsafe { unsf() }
+   |                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:178:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:188:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:189:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:190:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:196:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:207:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+LL |             unsf();
+LL |             unsafe { unsf() }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:208:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |             unsafe { unsf() }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:209:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |             unsafe { unsf() }
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:220:17
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |                 unsafe { unsf() }
+   |                 ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:218:20
+   |
+LL |             #[deny(unused_unsafe)]
+   |                    ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:221:17
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |                 unsafe { unsf() }
+   |                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:222:17
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+...
+LL |                 unsafe { unsf() }
+   |                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:242:9
+   |
+LL |         unsafe {
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:255:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+LL |             unsafe {
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:268:13
+   |
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+LL |             unsafe {
+   |             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:286:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:295:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:296:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:297:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:302:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:312:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             unsf();
+LL |             let _ = || unsafe { unsf() };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:313:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { unsf() };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:314:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { unsf() };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:324:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:322:20
+   |
+LL |             #[deny(unused_unsafe)]
+   |                    ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:325:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:326:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:336:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:346:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:347:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:348:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:354:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:365:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             unsf();
+LL |             let _ = || unsafe { unsf() };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:366:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { unsf() };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:367:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { unsf() };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:378:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:376:20
+   |
+LL |             #[deny(unused_unsafe)]
+   |                    ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:379:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:380:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:390:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:400:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:401:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:402:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:408:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:419:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             unsf();
+LL |             let _ = || unsafe { unsf() };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:420:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { unsf() };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:421:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { unsf() };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:432:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:430:20
+   |
+LL |             #[deny(unused_unsafe)]
+   |                    ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:433:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:434:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:454:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:467:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:480:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:499:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:508:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:509:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:510:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:515:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:525:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsf();
+LL |             let _ = || unsafe { let _ = || unsf(); };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:526:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { let _ = || unsf(); };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:527:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { let _ = || unsf(); };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:537:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { let _ = || unsf(); };
+   |                            ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:535:20
+   |
+LL |             #[deny(unused_unsafe)]
+   |                    ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:538:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { let _ = || unsf(); };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:539:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { let _ = || unsf(); };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:549:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:559:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:560:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:561:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:567:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:578:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsf();
+LL |             let _ = || unsafe { let _ = || unsf(); };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:579:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { let _ = || unsf(); };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:580:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { let _ = || unsf(); };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:591:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { let _ = || unsf(); };
+   |                            ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:589:20
+   |
+LL |             #[deny(unused_unsafe)]
+   |                    ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:592:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { let _ = || unsf(); };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:593:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { let _ = || unsf(); };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:603:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:613:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:614:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:615:24
+   |
+LL |             let _ = || unsafe {};
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:621:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:632:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsf();
+LL |             let _ = || unsafe { let _ = || unsf(); };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:633:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { let _ = || unsf(); };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:634:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |             let _ = || unsafe { let _ = || unsf(); };
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:645:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { let _ = || unsf(); };
+   |                            ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:643:20
+   |
+LL |             #[deny(unused_unsafe)]
+   |                    ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:646:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { let _ = || unsf(); };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:647:28
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { let _ = || unsf(); };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:667:20
+   |
+LL |         let _ = || unsafe {
+   |                    ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:680:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:693:24
+   |
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:711:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:721:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:722:28
+   |
+LL |                 let _ = || unsafe {};
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:723:28
+   |
+LL |                 let _ = || unsafe {};
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:729:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:740:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 unsf();
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:741:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:742:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:753:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:751:24
+   |
+LL |                 #[deny(unused_unsafe)]
+   |                        ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:754:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:755:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:765:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:775:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:776:28
+   |
+LL |                 let _ = || unsafe {};
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:777:28
+   |
+LL |                 let _ = || unsafe {};
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:783:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:794:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 unsf();
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:795:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:796:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:807:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:805:24
+   |
+LL |                 #[deny(unused_unsafe)]
+   |                        ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:808:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:809:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:829:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:842:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 let _ = || unsafe {
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:855:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 let _ = || unsafe {
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:869:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:879:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:880:28
+   |
+LL |                 let _ = || unsafe {};
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:881:28
+   |
+LL |                 let _ = || unsafe {};
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:887:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:898:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 unsf();
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:899:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:900:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:911:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:909:24
+   |
+LL |                 #[deny(unused_unsafe)]
+   |                        ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:912:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:913:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:923:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:933:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:934:28
+   |
+LL |                 let _ = || unsafe {};
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:935:28
+   |
+LL |                 let _ = || unsafe {};
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:941:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:952:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 unsf();
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:953:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:954:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = || unsafe { unsf() };
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:965:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-unsafe.rs:963:24
+   |
+LL |                 #[deny(unused_unsafe)]
+   |                        ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:966:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:967:32
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+...
+LL |                     let _ = || unsafe { unsf() };
+   |                                ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:987:24
+   |
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1000:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 let _ = || unsafe {
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1013:28
+   |
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 let _ = || unsafe {
+   |                            ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1059:29
+   |
+LL |             let _ = async { unsafe {
+   |                             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1066:33
+   |
+LL |             let _ = async { unsafe {
+   |                             ------ because it's nested under this `unsafe` block
+LL |                 let _ = async { unsf() };
+LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
+   |                                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1067:33
+   |
+LL |             let _ = async { unsafe {
+   |                             ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
+   |                                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1068:33
+   |
+LL |             let _ = async { unsafe {
+   |                             ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
+   |                                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1073:29
+   |
+LL |             let _ = async { unsafe {
+   |                             ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1080:33
+   |
+LL |             let _ = async { unsafe {
+   |                             ------ because it's nested under this `unsafe` block
+LL |                 let _ = async { unsf() };
+LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
+   |                                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1081:33
+   |
+LL |             let _ = async { unsafe {
+   |                             ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
+   |                                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1082:33
+   |
+LL |             let _ = async { unsafe {
+   |                             ------ because it's nested under this `unsafe` block
+...
+LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
+   |                                 ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1092:22
+   |
+LL |         let _x: [(); unsafe { 0 }] = [];
+   |                      ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:1096:22
+   |
+LL |         let _x: [(); unsafe { unsafe { size() } }] = [];
+   |                      ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 174 previous errors
+
diff --git a/tests/ui/span/lint-unused-unsafe.rs b/tests/ui/span/lint-unused-unsafe.rs
new file mode 100644
index 00000000000..5d042768be0
--- /dev/null
+++ b/tests/ui/span/lint-unused-unsafe.rs
@@ -0,0 +1,1100 @@
+// Exercise the unused_unsafe attribute in some positive and negative cases
+
+
+// edition:2018
+
+// revisions: mir
+
+// FIXME: Adapt -Zthir-unsafeck to behave the same as the mir version after #93678,
+// then delete lint-unused-unsafe-thir.rs, and go back to using the settings below
+// // revisions: mir thir
+// // [thir]compile-flags: -Zthir-unsafeck
+
+#![allow(dead_code)]
+#![deny(unused_unsafe)]
+
+
+mod foo {
+    extern "C" {
+        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() } }
+fn bad6() {
+    unsafe {                             //~ ERROR: unnecessary `unsafe` block
+        unsafe {                         // don't put the warning here
+            unsf()
+        }
+    }
+}
+unsafe fn bad7() {
+    unsafe {                             //~ ERROR: unnecessary `unsafe` block
+        unsafe {
+            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() {}
+
+mod additional_tests {
+    unsafe fn unsf() {}
+
+    // some tests
+
+    fn inner_ignored() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            #[allow(unused_unsafe)]
+            unsafe {
+                unsf()
+            }
+        }
+    }
+
+    fn multi_level_unused() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            unsafe {} //~ ERROR: unnecessary `unsafe` block
+            unsafe {} //~ ERROR: unnecessary `unsafe` block
+        }
+    }
+
+    fn granularity() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() }
+            unsafe { unsf() }
+            unsafe { unsf() }
+        }
+    }
+
+    fn top_level_used() {
+        unsafe {
+            unsf();
+            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+        }
+
+    }
+
+    fn top_level_ignored() {
+        #[allow(unused_unsafe)]
+        unsafe {
+            #[deny(unused_unsafe)]
+            {
+                unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+                unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+                unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            }
+        }
+
+    }
+
+    // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn inner_ignored_1() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            #[allow(unused_unsafe)]
+            unsafe {
+                unsf()
+            }
+        }
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn multi_level_unused_1() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            unsafe {} //~ ERROR: unnecessary `unsafe` block
+            unsafe {} //~ ERROR: unnecessary `unsafe` block
+        }
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn granularity_1() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() }
+            unsafe { unsf() }
+            unsafe { unsf() }
+        }
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_used_1() {
+        unsafe {
+            unsf();
+            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+        }
+
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_ignored_1() {
+        #[allow(unused_unsafe)]
+        unsafe {
+            #[deny(unused_unsafe)]
+            {
+                unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+                unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+                unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            }
+        }
+    }
+
+    // same tests, but unsafe_op_in_unsafe_fn allowed,
+    // so that *all* unsafe blocks are unused
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn inner_ignored_2() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            #[allow(unused_unsafe)]
+            unsafe {
+                unsf()
+            }
+        }
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn multi_level_unused_2() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            unsafe {} //~ ERROR: unnecessary `unsafe` block
+            unsafe {} //~ ERROR: unnecessary `unsafe` block
+        }
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granularity_2() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() }
+            unsafe { unsf() }
+            unsafe { unsf() }
+        }
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_used_2() {
+        unsafe {
+            unsf();
+            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+        }
+
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_ignored_2() {
+        #[allow(unused_unsafe)]
+        unsafe {
+            #[deny(unused_unsafe)]
+            {
+                unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+                unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+                unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            }
+        }
+    }
+
+    // additional tests when using unsafe_op_in_unsafe_fn
+    // in more complex ways
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn() {
+        unsafe {
+            #[deny(unsafe_op_in_unsafe_fn)]
+            {
+                unsf();
+            }
+        }
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn_2() {
+        unsafe { //~ ERROR: unnecessary `unsafe` block
+            unsafe {
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    unsf();
+                }
+            }
+        }
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn_3() {
+        unsafe {
+            unsafe { //~ ERROR: unnecessary `unsafe` block
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    unsf();
+                }
+            }
+            unsf();
+        }
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn_4() {
+        unsafe {
+            unsafe { //~ ERROR: unnecessary `unsafe` block
+                unsf();
+            }
+            #[deny(unsafe_op_in_unsafe_fn)]
+            {
+                unsf();
+            }
+        }
+    }
+}
+
+// the same set of tests, with closures everywhere
+mod additional_tests_closures {
+    unsafe fn unsf() {}
+
+    // some tests
+
+    fn inner_ignored() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                unsf()
+            };
+        };
+    }
+
+    fn multi_level_unused() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+        };
+    }
+
+    fn granularity() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() };
+            let _ = || unsafe { unsf() };
+            let _ = || unsafe { unsf() };
+        };
+    }
+
+    fn top_level_used() {
+        let _ = || unsafe {
+            unsf();
+            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+        };
+
+    }
+
+    fn top_level_ignored() {
+        #[allow(unused_unsafe)]
+        let _ = || unsafe {
+            #[deny(unused_unsafe)]
+            {
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            }
+        };
+
+    }
+
+    // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn inner_ignored_1() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                unsf()
+            };
+        };
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn multi_level_unused_1() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+        };
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn granularity_1() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() };
+            let _ = || unsafe { unsf() };
+            let _ = || unsafe { unsf() };
+        };
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_used_1() {
+        let _ = || unsafe {
+            unsf();
+            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+        };
+
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_ignored_1() {
+        #[allow(unused_unsafe)]
+        let _ = || unsafe {
+            #[deny(unused_unsafe)]
+            {
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            }
+        };
+    }
+
+    // same tests, but unsafe_op_in_unsafe_fn allowed,
+    // so that *all* unsafe blocks are unused
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn inner_ignored_2() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                unsf()
+            };
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn multi_level_unused_2() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granularity_2() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() };
+            let _ = || unsafe { unsf() };
+            let _ = || unsafe { unsf() };
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_used_2() {
+        let _ = || unsafe {
+            unsf();
+            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+        };
+
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_ignored_2() {
+        #[allow(unused_unsafe)]
+        let _ = || unsafe {
+            #[deny(unused_unsafe)]
+            {
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            }
+        };
+    }
+
+    // additional tests when using unsafe_op_in_unsafe_fn
+    // in more complex ways
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn() {
+        let _ = || unsafe {
+            #[deny(unsafe_op_in_unsafe_fn)]
+            {
+                unsf();
+            }
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn_2() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    unsf();
+                }
+            };
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn_3() {
+        let _ = || unsafe {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    unsf();
+                }
+            };
+            unsf();
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn_4() {
+        let _ = || unsafe {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                unsf();
+            };
+            #[deny(unsafe_op_in_unsafe_fn)]
+            {
+                unsf();
+            }
+        };
+    }
+}
+
+// the same set of tests, with closures everywhere
+// and closures on the unsafe fn calls
+mod additional_tests_even_more_closures {
+    unsafe fn unsf() {}
+
+    // some tests
+
+    fn inner_ignored() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                let _ = || unsf();
+            };
+        };
+    }
+
+    fn multi_level_unused() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+        };
+    }
+
+    fn granularity() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); };
+            let _ = || unsafe { let _ = || unsf(); };
+            let _ = || unsafe { let _ = || unsf(); };
+        };
+    }
+
+    fn top_level_used() {
+        let _ = || unsafe {
+            let _ = || unsf();
+            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+        };
+
+    }
+
+    fn top_level_ignored() {
+        #[allow(unused_unsafe)]
+        let _ = || unsafe {
+            #[deny(unused_unsafe)]
+            {
+                let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            }
+        };
+
+    }
+
+    // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn inner_ignored_1() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                let _ = || unsf();
+            };
+        };
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn multi_level_unused_1() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+        };
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn granularity_1() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); };
+            let _ = || unsafe { let _ = || unsf(); };
+            let _ = || unsafe { let _ = || unsf(); };
+        };
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_used_1() {
+        let _ = || unsafe {
+            let _ = || unsf();
+            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+        };
+
+    }
+
+    #[deny(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_ignored_1() {
+        #[allow(unused_unsafe)]
+        let _ = || unsafe {
+            #[deny(unused_unsafe)]
+            {
+                let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            }
+        };
+    }
+
+    // same tests, but unsafe_op_in_unsafe_fn allowed,
+    // so that *all* unsafe blocks are unused
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn inner_ignored_2() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                let _ = || unsf();
+            };
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn multi_level_unused_2() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granularity_2() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); };
+            let _ = || unsafe { let _ = || unsf(); };
+            let _ = || unsafe { let _ = || unsf(); };
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_used_2() {
+        let _ = || unsafe {
+            let _ = || unsf();
+            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+        };
+
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn top_level_ignored_2() {
+        #[allow(unused_unsafe)]
+        let _ = || unsafe {
+            #[deny(unused_unsafe)]
+            {
+                let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            }
+        };
+    }
+
+    // additional tests when using unsafe_op_in_unsafe_fn
+    // in more complex ways
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn() {
+        let _ = || unsafe {
+            #[deny(unsafe_op_in_unsafe_fn)]
+            {
+                let _ = || unsf();
+            }
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn_2() {
+        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    let _ = || unsf();
+                }
+            };
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn_3() {
+        let _ = || unsafe {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    let _ = || unsf();
+                }
+            };
+            let _ = || unsf();
+        };
+    }
+
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn_4() {
+        let _ = || unsafe {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsf();
+            };
+            #[deny(unsafe_op_in_unsafe_fn)]
+            {
+                let _ = || unsf();
+            }
+        };
+    }
+}
+
+mod item_likes {
+    unsafe fn unsf() {}
+
+    struct S;
+    impl S {
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn inner_ignored_1() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                #[allow(unused_unsafe)]
+                let _ = || unsafe {
+                    unsf()
+                };
+            };
+        }
+
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn multi_level_unused_1() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            };
+        }
+
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn granularity_1() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+            };
+        }
+
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn top_level_used_1() {
+            let _ = || unsafe {
+                unsf();
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            };
+
+        }
+
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn top_level_ignored_1() {
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                #[deny(unused_unsafe)]
+                {
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                }
+            };
+        }
+
+        // same tests, but unsafe_op_in_unsafe_fn allowed,
+        // so that *all* unsafe blocks are unused
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn inner_ignored_2() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                #[allow(unused_unsafe)]
+                let _ = || unsafe {
+                    unsf()
+                };
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn multi_level_unused_2() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granularity_2() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn top_level_used_2() {
+            let _ = || unsafe {
+                unsf();
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            };
+
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn top_level_ignored_2() {
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                #[deny(unused_unsafe)]
+                {
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                }
+            };
+        }
+
+        // additional tests when using unsafe_op_in_unsafe_fn
+        // in more complex ways
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granular_disallow_op_in_unsafe_fn() {
+            let _ = || unsafe {
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    unsf();
+                }
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granular_disallow_op_in_unsafe_fn_2() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {
+                    #[deny(unsafe_op_in_unsafe_fn)]
+                    {
+                        unsf();
+                    }
+                };
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granular_disallow_op_in_unsafe_fn_3() {
+            let _ = || unsafe {
+                let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                    #[deny(unsafe_op_in_unsafe_fn)]
+                    {
+                        unsf();
+                    }
+                };
+                unsf();
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granular_disallow_op_in_unsafe_fn_4() {
+            let _ = || unsafe {
+                let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                    unsf();
+                };
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    unsf();
+                }
+            };
+        }
+    }
+
+    trait T {
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn inner_ignored_1() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                #[allow(unused_unsafe)]
+                let _ = || unsafe {
+                    unsf()
+                };
+            };
+        }
+
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn multi_level_unused_1() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            };
+        }
+
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn granularity_1() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+            };
+        }
+
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn top_level_used_1() {
+            let _ = || unsafe {
+                unsf();
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            };
+
+        }
+
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn top_level_ignored_1() {
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                #[deny(unused_unsafe)]
+                {
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                }
+            };
+        }
+
+        // same tests, but unsafe_op_in_unsafe_fn allowed,
+        // so that *all* unsafe blocks are unused
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn inner_ignored_2() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                #[allow(unused_unsafe)]
+                let _ = || unsafe {
+                    unsf()
+                };
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn multi_level_unused_2() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granularity_2() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn top_level_used_2() {
+            let _ = || unsafe {
+                unsf();
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            };
+
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn top_level_ignored_2() {
+            #[allow(unused_unsafe)]
+            let _ = || unsafe {
+                #[deny(unused_unsafe)]
+                {
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                    let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                }
+            };
+        }
+
+        // additional tests when using unsafe_op_in_unsafe_fn
+        // in more complex ways
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granular_disallow_op_in_unsafe_fn() {
+            let _ = || unsafe {
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    unsf();
+                }
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granular_disallow_op_in_unsafe_fn_2() {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe {
+                    #[deny(unsafe_op_in_unsafe_fn)]
+                    {
+                        unsf();
+                    }
+                };
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granular_disallow_op_in_unsafe_fn_3() {
+            let _ = || unsafe {
+                let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                    #[deny(unsafe_op_in_unsafe_fn)]
+                    {
+                        unsf();
+                    }
+                };
+                unsf();
+            };
+        }
+
+        #[allow(unsafe_op_in_unsafe_fn)]
+        unsafe fn granular_disallow_op_in_unsafe_fn_4() {
+            let _ = || unsafe {
+                let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+                    unsf();
+                };
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    unsf();
+                }
+            };
+        }
+    }
+}
+
+mod additional_tests_extra {
+    unsafe fn unsf() {}
+
+    // multiple uses with different `unsafe_op_in_unsafe_fn` in the same closure
+    #[allow(unsafe_op_in_unsafe_fn)]
+    unsafe fn granular_disallow_op_in_unsafe_fn() {
+        let _ = || unsafe {
+            let _ = || {
+                unsf();
+                #[deny(unsafe_op_in_unsafe_fn)]
+                {
+                    unsf();
+                }
+            };
+        };
+    }
+
+    #[warn(unsafe_op_in_unsafe_fn)]
+    unsafe fn multiple_unsafe_op_in_unsafe_fn_allows() {
+        unsafe {
+            #[allow(unsafe_op_in_unsafe_fn)]
+            {
+                unsf();
+            }
+            #[allow(unsafe_op_in_unsafe_fn)]
+            {
+                unsf();
+            }
+        }
+    }
+
+    async unsafe fn async_blocks() {
+        #[deny(unsafe_op_in_unsafe_fn)]
+        {
+            let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = async { unsafe { let _ = async { unsf() }; }};
+                let _ = async { unsafe { let _ = async { unsf() }; }};
+                let _ = async { unsafe { let _ = async { unsf() }; }};
+            }};
+            let _ = async { unsafe {
+                let _ = async { unsf() };
+                let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
+                let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
+                let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
+            }};
+        }
+        #[allow(unsafe_op_in_unsafe_fn)]
+        {
+            let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block
+                let _ = async { unsafe { let _ = async { unsf() }; }};
+                let _ = async { unsafe { let _ = async { unsf() }; }};
+                let _ = async { unsafe { let _ = async { unsf() }; }};
+            }};
+            let _ = async { unsafe {
+                let _ = async { unsf() };
+                let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
+                let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
+                let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
+            }};
+        }
+    }
+
+    fn used_unsafe_in_const() {
+        let _x: [(); unsafe { size() }] = [];
+    }
+
+    fn unused_unsafe_in_const_1() {
+        let _x: [(); unsafe { 0 }] = []; //~ ERROR: unnecessary `unsafe` block
+    }
+
+    fn unused_unsafe_in_const_2() {
+        let _x: [(); unsafe { unsafe { size() } }] = []; //~ ERROR: unnecessary `unsafe` block
+    }
+
+    const unsafe fn size() -> usize { 0 }
+}
diff --git a/tests/ui/span/macro-span-replacement.rs b/tests/ui/span/macro-span-replacement.rs
new file mode 100644
index 00000000000..66973c58d35
--- /dev/null
+++ b/tests/ui/span/macro-span-replacement.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+#![warn(unused)]
+
+macro_rules! m {
+    ($a:tt $b:tt) => {
+        $b $a; //~ WARN struct `S` is never constructed
+    }
+}
+
+fn main() {
+    m!(S struct);
+}
diff --git a/tests/ui/span/macro-span-replacement.stderr b/tests/ui/span/macro-span-replacement.stderr
new file mode 100644
index 00000000000..5dd56342889
--- /dev/null
+++ b/tests/ui/span/macro-span-replacement.stderr
@@ -0,0 +1,19 @@
+warning: struct `S` is never constructed
+  --> $DIR/macro-span-replacement.rs:7:12
+   |
+LL |         $b $a;
+   |            ^^
+...
+LL |     m!(S struct);
+   |     ------------ in this macro invocation
+   |
+note: the lint level is defined here
+  --> $DIR/macro-span-replacement.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
+   = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/span/macro-ty-params.rs b/tests/ui/span/macro-ty-params.rs
new file mode 100644
index 00000000000..cf28b0255d1
--- /dev/null
+++ b/tests/ui/span/macro-ty-params.rs
@@ -0,0 +1,15 @@
+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 unexpected generic arguments in path
+    //~^^ ERROR generic arguments in macro path
+}
diff --git a/tests/ui/span/macro-ty-params.stderr b/tests/ui/span/macro-ty-params.stderr
new file mode 100644
index 00000000000..7023ef8cd1c
--- /dev/null
+++ b/tests/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:15
+   |
+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/tests/ui/span/method-and-field-eager-resolution.rs b/tests/ui/span/method-and-field-eager-resolution.rs
new file mode 100644
index 00000000000..a0f0d8810e5
--- /dev/null
+++ b/tests/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();
+    //~^ ERROR type annotations needed
+    x.0;
+    x = 1;
+}
+
+fn foo() {
+    let mut x = Default::default();
+    //~^ ERROR type annotations needed
+    x[0];
+    x = 1;
+}
diff --git a/tests/ui/span/method-and-field-eager-resolution.stderr b/tests/ui/span/method-and-field-eager-resolution.stderr
new file mode 100644
index 00000000000..f6efbe40bc2
--- /dev/null
+++ b/tests/ui/span/method-and-field-eager-resolution.stderr
@@ -0,0 +1,31 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-and-field-eager-resolution.rs:4:9
+   |
+LL |     let mut x = Default::default();
+   |         ^^^^^
+LL |
+LL |     x.0;
+   |     - type must be known at this point
+   |
+help: consider giving `x` an explicit type
+   |
+LL |     let mut x: /* Type */ = Default::default();
+   |              ++++++++++++
+
+error[E0282]: type annotations needed
+  --> $DIR/method-and-field-eager-resolution.rs:11:9
+   |
+LL |     let mut x = Default::default();
+   |         ^^^^^
+LL |
+LL |     x[0];
+   |     - type must be known at this point
+   |
+help: consider giving `x` an explicit type
+   |
+LL |     let mut x: /* Type */ = Default::default();
+   |              ++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/span/missing-unit-argument.rs b/tests/ui/span/missing-unit-argument.rs
new file mode 100644
index 00000000000..db96ae223d9
--- /dev/null
+++ b/tests/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 enum variant takes
+    foo(); //~ ERROR function takes
+    foo(()); //~ ERROR function takes
+    bar(); //~ ERROR function takes
+    S.baz(); //~ ERROR this method takes
+    S.generic::<()>(); //~ ERROR this method takes
+}
diff --git a/tests/ui/span/missing-unit-argument.stderr b/tests/ui/span/missing-unit-argument.stderr
new file mode 100644
index 00000000000..ef4d732b51d
--- /dev/null
+++ b/tests/ui/span/missing-unit-argument.stderr
@@ -0,0 +1,96 @@
+error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
+  --> $DIR/missing-unit-argument.rs:11:33
+   |
+LL |     let _: Result<(), String> = Ok();
+   |                                 ^^-- an argument of type `()` is missing
+   |
+note: tuple variant defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+help: provide the argument
+   |
+LL |     let _: Result<(), String> = Ok(());
+   |                                   ~~~~
+
+error[E0061]: this function takes 2 arguments but 0 arguments were supplied
+  --> $DIR/missing-unit-argument.rs:12:5
+   |
+LL |     foo();
+   |     ^^^-- two arguments of type `()` and `()` are missing
+   |
+note: function defined here
+  --> $DIR/missing-unit-argument.rs:1:4
+   |
+LL | fn foo(():(), ():()) {}
+   |    ^^^ -----  -----
+help: provide the arguments
+   |
+LL |     foo((), ());
+   |        ~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/missing-unit-argument.rs:13:5
+   |
+LL |     foo(());
+   |     ^^^---- an argument of type `()` is missing
+   |
+note: function defined here
+  --> $DIR/missing-unit-argument.rs:1:4
+   |
+LL | fn foo(():(), ():()) {}
+   |    ^^^ -----  -----
+help: provide the argument
+   |
+LL |     foo((), ());
+   |        ~~~~~~~~
+
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/missing-unit-argument.rs:14:5
+   |
+LL |     bar();
+   |     ^^^-- an argument of type `()` is missing
+   |
+note: function defined here
+  --> $DIR/missing-unit-argument.rs:2:4
+   |
+LL | fn bar(():()) {}
+   |    ^^^ -----
+help: provide the argument
+   |
+LL |     bar(());
+   |        ~~~~
+
+error[E0061]: this method takes 1 argument but 0 arguments were supplied
+  --> $DIR/missing-unit-argument.rs:15:7
+   |
+LL |     S.baz();
+   |       ^^^-- an argument of type `()` is missing
+   |
+note: associated function defined here
+  --> $DIR/missing-unit-argument.rs:6:8
+   |
+LL |     fn baz(self, (): ()) { }
+   |        ^^^       ------
+help: provide the argument
+   |
+LL |     S.baz(());
+   |          ~~~~
+
+error[E0061]: this method takes 1 argument but 0 arguments were supplied
+  --> $DIR/missing-unit-argument.rs:16:7
+   |
+LL |     S.generic::<()>();
+   |       ^^^^^^^^^^^^^-- an argument of type `()` is missing
+   |
+note: associated function defined here
+  --> $DIR/missing-unit-argument.rs:7:8
+   |
+LL |     fn generic<T>(self, _: T) { }
+   |        ^^^^^^^          ----
+help: provide the argument
+   |
+LL |     S.generic::<()>(());
+   |                    ~~~~
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/span/move-closure.rs b/tests/ui/span/move-closure.rs
new file mode 100644
index 00000000000..bdd7951b303
--- /dev/null
+++ b/tests/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/tests/ui/span/move-closure.stderr b/tests/ui/span/move-closure.stderr
new file mode 100644
index 00000000000..dcc60789694
--- /dev/null
+++ b/tests/ui/span/move-closure.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/move-closure.rs:5:17
+   |
+LL |     let x: () = move || ();
+   |            --   ^^^^^^^^^^ expected `()`, found closure
+   |            |
+   |            expected due to this
+   |
+   = note: expected unit type `()`
+                found closure `[closure@$DIR/move-closure.rs:5:17: 5:24]`
+help: use parentheses to call this closure
+   |
+LL |     let x: () = (move || ())();
+   |                 +          +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/span/multiline-span-E0072.rs b/tests/ui/span/multiline-span-E0072.rs
new file mode 100644
index 00000000000..728b47d6539
--- /dev/null
+++ b/tests/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/tests/ui/span/multiline-span-E0072.stderr b/tests/ui/span/multiline-span-E0072.stderr
new file mode 100644
index 00000000000..fc2f6e6622c
--- /dev/null
+++ b/tests/ui/span/multiline-span-E0072.stderr
@@ -0,0 +1,18 @@
+error[E0072]: recursive type `ListNode` has infinite size
+  --> $DIR/multiline-span-E0072.rs:2:1
+   |
+LL | / struct
+LL | | ListNode
+   | |________^
+...
+LL |       tail: Option<ListNode>,
+   |                    -------- recursive without indirection
+   |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+   |
+LL |     tail: Option<Box<ListNode>>,
+   |                  ++++        +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/ui/span/multiline-span-simple.rs b/tests/ui/span/multiline-span-simple.rs
new file mode 100644
index 00000000000..204a7f6b1b2
--- /dev/null
+++ b/tests/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/tests/ui/span/multiline-span-simple.stderr b/tests/ui/span/multiline-span-simple.stderr
new file mode 100644
index 00000000000..b44df962a9b
--- /dev/null
+++ b/tests/ui/span/multiline-span-simple.stderr
@@ -0,0 +1,16 @@
+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 `Add<()>` is not implemented for `u32`
+   = help: the following other types implement trait `Add<Rhs>`:
+             <&'a u32 as Add<u32>>
+             <&u32 as Add<&u32>>
+             <u32 as Add<&u32>>
+             <u32 as Add>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/span/multispan-import-lint.rs b/tests/ui/span/multispan-import-lint.rs
new file mode 100644
index 00000000000..3ce7f2ce35d
--- /dev/null
+++ b/tests/ui/span/multispan-import-lint.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#![warn(unused)]
+
+use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
+//~^ WARN unused imports
+
+fn main() {
+    let _ = min(1, 2);
+}
diff --git a/tests/ui/span/multispan-import-lint.stderr b/tests/ui/span/multispan-import-lint.stderr
new file mode 100644
index 00000000000..4a955d1b31f
--- /dev/null
+++ b/tests/ui/span/multispan-import-lint.stderr
@@ -0,0 +1,15 @@
+warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`
+  --> $DIR/multispan-import-lint.rs:5:16
+   |
+LL | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
+   |                ^^  ^^^       ^^^^^^^^^  ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/multispan-import-lint.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_imports)]` implied by `#[warn(unused)]`
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/span/mut-arg-hint.rs b/tests/ui/span/mut-arg-hint.rs
new file mode 100644
index 00000000000..d7ff1f0de41
--- /dev/null
+++ b/tests/ui/span/mut-arg-hint.rs
@@ -0,0 +1,22 @@
+trait B {
+    fn foo(mut a: &String) {
+        a.push_str("bar"); //~ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference
+    }
+}
+
+pub fn foo<'a>(mut a: &'a String) {
+    a.push_str("foo"); //~ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference
+}
+
+struct A {}
+
+impl A {
+    pub fn foo(mut a: &String) {
+        a.push_str("foo"); //~ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference
+    }
+}
+
+fn main() {
+    foo(&"a".to_string());
+    A::foo(&"a".to_string());
+}
diff --git a/tests/ui/span/mut-arg-hint.stderr b/tests/ui/span/mut-arg-hint.stderr
new file mode 100644
index 00000000000..96ce4d5bc6c
--- /dev/null
+++ b/tests/ui/span/mut-arg-hint.stderr
@@ -0,0 +1,36 @@
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
+  --> $DIR/mut-arg-hint.rs:3:9
+   |
+LL |         a.push_str("bar");
+   |         ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL |     fn foo(mut a: &mut String) {
+   |                   ~~~~~~~~~~~
+
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
+  --> $DIR/mut-arg-hint.rs:8:5
+   |
+LL |     a.push_str("foo");
+   |     ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL | pub fn foo<'a>(mut a: &'a mut String) {
+   |                       ~~~~~~~~~~~~~~
+
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
+  --> $DIR/mut-arg-hint.rs:15:9
+   |
+LL |         a.push_str("foo");
+   |         ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+   |
+help: consider changing this to be a mutable reference
+   |
+LL |     pub fn foo(mut a: &mut String) {
+   |                       ~~~~~~~~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/span/mut-ptr-cant-outlive-ref.rs b/tests/ui/span/mut-ptr-cant-outlive-ref.rs
new file mode 100644
index 00000000000..b8c752d73ed
--- /dev/null
+++ b/tests/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/tests/ui/span/mut-ptr-cant-outlive-ref.stderr b/tests/ui/span/mut-ptr-cant-outlive-ref.stderr
new file mode 100644
index 00000000000..4d976a7bbfa
--- /dev/null
+++ b/tests/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 |
+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/tests/ui/span/non-existing-module-import.rs b/tests/ui/span/non-existing-module-import.rs
new file mode 100644
index 00000000000..d2ce7ec4f8e
--- /dev/null
+++ b/tests/ui/span/non-existing-module-import.rs
@@ -0,0 +1,3 @@
+use std::bar::{foo1, foo2}; //~ ERROR unresolved import
+
+fn main() {}
diff --git a/tests/ui/span/non-existing-module-import.stderr b/tests/ui/span/non-existing-module-import.stderr
new file mode 100644
index 00000000000..25c09959047
--- /dev/null
+++ b/tests/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/tests/ui/span/pub-struct-field.rs b/tests/ui/span/pub-struct-field.rs
new file mode 100644
index 00000000000..e149b9dbf5a
--- /dev/null
+++ b/tests/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/tests/ui/span/pub-struct-field.stderr b/tests/ui/span/pub-struct-field.stderr
new file mode 100644
index 00000000000..065340f446a
--- /dev/null
+++ b/tests/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/tests/ui/span/range-2.rs b/tests/ui/span/range-2.rs
new file mode 100644
index 00000000000..c4bb16f44bd
--- /dev/null
+++ b/tests/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/tests/ui/span/range-2.stderr b/tests/ui/span/range-2.stderr
new file mode 100644
index 00000000000..8ca8156b083
--- /dev/null
+++ b/tests/ui/span/range-2.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/tests/ui/span/recursive-type-field.rs b/tests/ui/span/recursive-type-field.rs
new file mode 100644
index 00000000000..bd4c435347c
--- /dev/null
+++ b/tests/ui/span/recursive-type-field.rs
@@ -0,0 +1,18 @@
+use std::rc::Rc;
+
+struct Foo<'a> { //~ ERROR recursive types `Foo` and `Bar` have infinite size
+    bar: Bar<'a>,
+    b: Rc<Bar<'a>>,
+}
+
+struct Bar<'a> {
+    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/tests/ui/span/recursive-type-field.stderr b/tests/ui/span/recursive-type-field.stderr
new file mode 100644
index 00000000000..10af4c36ba4
--- /dev/null
+++ b/tests/ui/span/recursive-type-field.stderr
@@ -0,0 +1,27 @@
+error[E0072]: recursive types `Foo` and `Bar` have infinite size
+  --> $DIR/recursive-type-field.rs:3:1
+   |
+LL | struct Foo<'a> {
+   | ^^^^^^^^^^^^^^
+LL |     bar: Bar<'a>,
+   |          ------- recursive without indirection
+...
+LL | struct Bar<'a> {
+   | ^^^^^^^^^^^^^^
+LL |     y: (Foo<'a>, Foo<'a>),
+   |         -------  ------- recursive without indirection
+   |         |
+   |         recursive without indirection
+   |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+   |
+LL ~     bar: Box<Bar<'a>>,
+LL |     b: Rc<Bar<'a>>,
+ ...
+LL | struct Bar<'a> {
+LL ~     y: (Box<Foo<'a>>, Box<Foo<'a>>),
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs
new file mode 100644
index 00000000000..60ccaa872e7
--- /dev/null
+++ b/tests/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/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
new file mode 100644
index 00000000000..0b985de609c
--- /dev/null
+++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.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/tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs
new file mode 100644
index 00000000000..16b4cc25862
--- /dev/null
+++ b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs
@@ -0,0 +1,16 @@
+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 temporary value dropped while borrowed
+        blah = Box::new(ss) as Box<dyn Foo>;
+    }
+}
diff --git a/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr
new file mode 100644
index 00000000000..81e858fa0ce
--- /dev/null
+++ b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.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 value 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 `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/tests/ui/span/regions-close-over-type-parameter-2.rs b/tests/ui/span/regions-close-over-type-parameter-2.rs
new file mode 100644
index 00000000000..aca3972cb6c
--- /dev/null
+++ b/tests/ui/span/regions-close-over-type-parameter-2.rs
@@ -0,0 +1,27 @@
+// 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<dyn Foo + 'a> {
+    Box::new(v) as Box<dyn 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/tests/ui/span/regions-close-over-type-parameter-2.stderr b/tests/ui/span/regions-close-over-type-parameter-2.stderr
new file mode 100644
index 00000000000..2e584d9a884
--- /dev/null
+++ b/tests/ui/span/regions-close-over-type-parameter-2.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/tests/ui/span/regions-escape-loop-via-variable.rs b/tests/ui/span/regions-escape-loop-via-variable.rs
new file mode 100644
index 00000000000..ad468896b13
--- /dev/null
+++ b/tests/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/tests/ui/span/regions-escape-loop-via-variable.stderr b/tests/ui/span/regions-escape-loop-via-variable.stderr
new file mode 100644
index 00000000000..42df6685297
--- /dev/null
+++ b/tests/ui/span/regions-escape-loop-via-variable.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/tests/ui/span/regions-escape-loop-via-vec.rs b/tests/ui/span/regions-escape-loop-via-vec.rs
new file mode 100644
index 00000000000..1fceb096967
--- /dev/null
+++ b/tests/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 use `x` because it was mutably borrowed
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/span/regions-escape-loop-via-vec.stderr b/tests/ui/span/regions-escape-loop-via-vec.stderr
new file mode 100644
index 00000000000..2b649307739
--- /dev/null
+++ b/tests/ui/span/regions-escape-loop-via-vec.stderr
@@ -0,0 +1,50 @@
+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 have detailed explanations: E0503, E0597.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/tests/ui/span/regions-infer-borrow-scope-within-loop.rs b/tests/ui/span/regions-infer-borrow-scope-within-loop.rs
new file mode 100644
index 00000000000..3b20285b1bf
--- /dev/null
+++ b/tests/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/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr b/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr
new file mode 100644
index 00000000000..fd67c65c4e9
--- /dev/null
+++ b/tests/ui/span/regions-infer-borrow-scope-within-loop.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/tests/ui/span/send-is-not-static-ensures-scoping.rs b/tests/ui/span/send-is-not-static-ensures-scoping.rs
new file mode 100644
index 00000000000..2aecc2a7e0d
--- /dev/null
+++ b/tests/ui/span/send-is-not-static-ensures-scoping.rs
@@ -0,0 +1,26 @@
+struct Guard<'a> {
+    f: Box<dyn 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/tests/ui/span/send-is-not-static-ensures-scoping.stderr b/tests/ui/span/send-is-not-static-ensures-scoping.stderr
new file mode 100644
index 00000000000..65d10c1305b
--- /dev/null
+++ b/tests/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: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/tests/ui/span/send-is-not-static-std-sync-2.rs b/tests/ui/span/send-is-not-static-std-sync-2.rs
new file mode 100644
index 00000000000..38746d4cbbc
--- /dev/null
+++ b/tests/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/tests/ui/span/send-is-not-static-std-sync-2.stderr b/tests/ui/span/send-is-not-static-std-sync-2.stderr
new file mode 100644
index 00000000000..bcd07e11647
--- /dev/null
+++ b/tests/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: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/tests/ui/span/send-is-not-static-std-sync.rs b/tests/ui/span/send-is-not-static-std-sync.rs
new file mode 100644
index 00000000000..f8ab5243c22
--- /dev/null
+++ b/tests/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/tests/ui/span/send-is-not-static-std-sync.stderr b/tests/ui/span/send-is-not-static-std-sync.stderr
new file mode 100644
index 00000000000..5d493a3e4ee
--- /dev/null
+++ b/tests/ui/span/send-is-not-static-std-sync.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 `Sender`
+   |
+   = note: values in a scope are dropped in the opposite order they are defined
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0505, E0597.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/tests/ui/span/slice-borrow.rs b/tests/ui/span/slice-borrow.rs
new file mode 100644
index 00000000000..38cd7acbdfa
--- /dev/null
+++ b/tests/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 temporary value dropped while borrowed
+        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/tests/ui/span/slice-borrow.stderr b/tests/ui/span/slice-borrow.stderr
new file mode 100644
index 00000000000..b70bf69d688
--- /dev/null
+++ b/tests/ui/span/slice-borrow.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 value 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 the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/span/suggestion-non-ascii.rs b/tests/ui/span/suggestion-non-ascii.rs
new file mode 100644
index 00000000000..914efd85a0c
--- /dev/null
+++ b/tests/ui/span/suggestion-non-ascii.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let tup = (1,);
+    println!("☃{}", tup[0]); //~ ERROR cannot index into a value of type
+}
diff --git a/tests/ui/span/suggestion-non-ascii.stderr b/tests/ui/span/suggestion-non-ascii.stderr
new file mode 100644
index 00000000000..b14632d4e1b
--- /dev/null
+++ b/tests/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/tests/ui/span/transitive-dep-span.rs b/tests/ui/span/transitive-dep-span.rs
new file mode 100644
index 00000000000..2d46f74ad9b
--- /dev/null
+++ b/tests/ui/span/transitive-dep-span.rs
@@ -0,0 +1,15 @@
+// Tests that we properly serialize/deserialize spans from transitive dependencies
+// (e.g. imported SourceFiles)
+//
+// The order of these next lines is important, since we need
+// transitive_dep_two.rs to be able to reference transitive_dep_three.rs
+//
+// aux-build: transitive_dep_three.rs
+// aux-build: transitive_dep_two.rs
+// compile-flags: -Z macro-backtrace
+
+extern crate transitive_dep_two;
+
+transitive_dep_two::parse_error!(); //~ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/span/transitive-dep-span.stderr b/tests/ui/span/transitive-dep-span.stderr
new file mode 100644
index 00000000000..4dc3e572116
--- /dev/null
+++ b/tests/ui/span/transitive-dep-span.stderr
@@ -0,0 +1,18 @@
+error: expected one of `!` or `::`, found `error`
+  --> $DIR/auxiliary/transitive_dep_three.rs:6:27
+   |
+LL |         macro_rules! parse_error {
+   |         ------------------------ in this expansion of `transitive_dep_two::parse_error!`
+LL |             () => { parse error }
+   |                           ^^^^^ expected one of `!` or `::`
+   |
+  ::: $DIR/transitive-dep-span.rs:13:1
+   |
+LL | transitive_dep_two::parse_error!();
+   | ----------------------------------
+   | |
+   | in this macro invocation
+   | in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/tests/ui/span/type-annotations-needed-expr.rs b/tests/ui/span/type-annotations-needed-expr.rs
new file mode 100644
index 00000000000..f64dab4d7bc
--- /dev/null
+++ b/tests/ui/span/type-annotations-needed-expr.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _ = (vec![1,2,3]).into_iter().sum() as f64; //~ ERROR E0282
+}
diff --git a/tests/ui/span/type-annotations-needed-expr.stderr b/tests/ui/span/type-annotations-needed-expr.stderr
new file mode 100644
index 00000000000..9dff6c64db4
--- /dev/null
+++ b/tests/ui/span/type-annotations-needed-expr.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/type-annotations-needed-expr.rs:2:39
+   |
+LL |     let _ = (vec![1,2,3]).into_iter().sum() as f64;
+   |                                       ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
+   |
+help: consider specifying the generic argument
+   |
+LL |     let _ = (vec![1,2,3]).into_iter().sum::<S>() as f64;
+   |                                          +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/span/type-binding.rs b/tests/ui/span/type-binding.rs
new file mode 100644
index 00000000000..32016e1278f
--- /dev/null
+++ b/tests/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/tests/ui/span/type-binding.stderr b/tests/ui/span/type-binding.stderr
new file mode 100644
index 00000000000..cb0aefe0609
--- /dev/null
+++ b/tests/ui/span/type-binding.stderr
@@ -0,0 +1,9 @@
+error[E0220]: associated type `Trget` not found for `Deref`
+  --> $DIR/type-binding.rs:6:20
+   |
+LL | fn homura<T: Deref<Trget = i32>>(_: T) {}
+   |                    ^^^^^ help: there is an associated type with a similar name: `Target`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/span/typo-suggestion.rs b/tests/ui/span/typo-suggestion.rs
new file mode 100644
index 00000000000..e9d7bc65ef5
--- /dev/null
+++ b/tests/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/tests/ui/span/typo-suggestion.stderr b/tests/ui/span/typo-suggestion.stderr
new file mode 100644
index 00000000000..61d4e06119c
--- /dev/null
+++ b/tests/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/tests/ui/span/unused-warning-point-at-identifier.rs b/tests/ui/span/unused-warning-point-at-identifier.rs
new file mode 100644
index 00000000000..af4834503cd
--- /dev/null
+++ b/tests/ui/span/unused-warning-point-at-identifier.rs
@@ -0,0 +1,30 @@
+// run-pass
+
+#![warn(unused)]
+
+enum Enum { //~ WARN enum `Enum` is never used
+    A,
+    B,
+    C,
+    D,
+}
+
+struct Struct { //~ WARN struct `Struct` is never constructed
+    a: usize,
+    b: usize,
+    c: usize,
+    d: usize,
+}
+
+fn func() -> usize { //~ WARN function `func` is never used
+    3
+}
+
+fn
+func_complete_span() //~ WARN function `func_complete_span` is never used
+-> usize
+{
+    3
+}
+
+fn main() {}
diff --git a/tests/ui/span/unused-warning-point-at-identifier.stderr b/tests/ui/span/unused-warning-point-at-identifier.stderr
new file mode 100644
index 00000000000..c2cb5623194
--- /dev/null
+++ b/tests/ui/span/unused-warning-point-at-identifier.stderr
@@ -0,0 +1,33 @@
+warning: enum `Enum` is never used
+  --> $DIR/unused-warning-point-at-identifier.rs:5:6
+   |
+LL | enum Enum {
+   |      ^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-warning-point-at-identifier.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
+
+warning: struct `Struct` is never constructed
+  --> $DIR/unused-warning-point-at-identifier.rs:12:8
+   |
+LL | struct Struct {
+   |        ^^^^^^
+
+warning: function `func` is never used
+  --> $DIR/unused-warning-point-at-identifier.rs:19:4
+   |
+LL | fn func() -> usize {
+   |    ^^^^
+
+warning: function `func_complete_span` is never used
+  --> $DIR/unused-warning-point-at-identifier.rs:24:1
+   |
+LL | func_complete_span()
+   | ^^^^^^^^^^^^^^^^^^
+
+warning: 4 warnings emitted
+
diff --git a/tests/ui/span/vec-must-not-hide-type-from-dropck.rs b/tests/ui/span/vec-must-not-hide-type-from-dropck.rs
new file mode 100644
index 00000000000..9bfbfab06a0
--- /dev/null
+++ b/tests/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/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr b/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr
new file mode 100644
index 00000000000..f87c32d1ad0
--- /dev/null
+++ b/tests/ui/span/vec-must-not-hide-type-from-dropck.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/tests/ui/span/vec_refs_data_with_early_death.rs b/tests/ui/span/vec_refs_data_with_early_death.rs
new file mode 100644
index 00000000000..c23c5211549
--- /dev/null
+++ b/tests/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/tests/ui/span/vec_refs_data_with_early_death.stderr b/tests/ui/span/vec_refs_data_with_early_death.stderr
new file mode 100644
index 00000000000..684e7845313
--- /dev/null
+++ b/tests/ui/span/vec_refs_data_with_early_death.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/tests/ui/span/visibility-ty-params.rs b/tests/ui/span/visibility-ty-params.rs
new file mode 100644
index 00000000000..d77febe0aa2
--- /dev/null
+++ b/tests/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/tests/ui/span/visibility-ty-params.stderr b/tests/ui/span/visibility-ty-params.stderr
new file mode 100644
index 00000000000..067893fd22d
--- /dev/null
+++ b/tests/ui/span/visibility-ty-params.stderr
@@ -0,0 +1,21 @@
+error: unexpected generic arguments in path
+  --> $DIR/visibility-ty-params.rs:6:6
+   |
+LL | m!{ S<u8> }
+   |      ^^^^
+
+error[E0577]: expected module, found struct `S`
+  --> $DIR/visibility-ty-params.rs:6:5
+   |
+LL | m!{ S<u8> }
+   |     ^^^^^ not a module
+
+error: unexpected generic arguments in path
+  --> $DIR/visibility-ty-params.rs:10:10
+   |
+LL |     m!{ m<> }
+   |          ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0577`.
diff --git a/tests/ui/span/wf-method-late-bound-regions.rs b/tests/ui/span/wf-method-late-bound-regions.rs
new file mode 100644
index 00000000000..ca9f73d0acc
--- /dev/null
+++ b/tests/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/tests/ui/span/wf-method-late-bound-regions.stderr b/tests/ui/span/wf-method-late-bound-regions.stderr
new file mode 100644
index 00000000000..6b0b008208f
--- /dev/null
+++ b/tests/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: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`.