Auto merge of #67084 - Pagten:feature/print-msg-from-elf-entrypoint, r=Amanieu

SGX: Change ELF entrypoint

This fixes [rust-sgx issue #148](https://github.com/fortanix/rust-sgx/issues/148).

A new entry point is created for the ELF file generated by `rustc`, separate from the enclave entry point. When the ELF file is executed as a Linux binary, the error message below is written to stderr.

> Error: This file is an SGX enclave which cannot be executed as a standard Linux binary.
> See the installation guide at https://edp.fortanix.com/docs/installation/guide/ on how to use 'cargo run' or follow the steps at https://edp.fortanix.com/docs/tasks/deployment/ for manual deployment.

When the ELF file is converted to an SGXS using `elf2sgxs`, the old entry point is still set as the enclave entry point. In a future pull request in the rust-sgx repository, `elf2sgxs` will be modified to remove the code in the ELF entry point, since this code is not needed in the enclave.
diff --git a/Cargo.lock b/Cargo.lock
index 5e83513..1af0442 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -570,9 +570,9 @@
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.18"
+version = "0.1.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef1c086a06d6f52f9c0d50cacdc021bfb6034ddeec9fb7e62f099f13f65472f4"
+checksum = "e6f083abf9bb9005a27d2da62706f661245278cb7096da37ab27410eaf60f2c1"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -726,21 +726,11 @@
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
-dependencies = [
- "crossbeam-epoch 0.3.1",
- "crossbeam-utils 0.2.2",
-]
-
-[[package]]
-name = "crossbeam-deque"
 version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
 dependencies = [
- "crossbeam-epoch 0.7.2",
+ "crossbeam-epoch",
  "crossbeam-utils 0.6.5",
 ]
 
@@ -750,27 +740,12 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
 dependencies = [
- "crossbeam-epoch 0.7.2",
+ "crossbeam-epoch",
  "crossbeam-utils 0.6.5",
 ]
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
-dependencies = [
- "arrayvec",
- "cfg-if",
- "crossbeam-utils 0.2.2",
- "lazy_static 1.3.0",
- "memoffset 0.2.1",
- "nodrop",
- "scopeguard 0.3.3",
-]
-
-[[package]]
-name = "crossbeam-epoch"
 version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
@@ -779,7 +754,7 @@
  "cfg-if",
  "crossbeam-utils 0.6.5",
  "lazy_static 1.3.0",
- "memoffset 0.5.1",
+ "memoffset",
  "scopeguard 1.0.0",
 ]
 
@@ -794,15 +769,6 @@
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "crossbeam-utils"
 version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
@@ -1456,7 +1422,7 @@
  "markup5ever",
  "proc-macro2 1.0.3",
  "quote 1.0.2",
- "syn 1.0.5",
+ "syn 1.0.11",
 ]
 
 [[package]]
@@ -2055,12 +2021,13 @@
 
 [[package]]
 name = "measureme"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd21b0e6e1af976b269ce062038fe5e1b9ca2f817ab7a3af09ec4210aebf0d30"
+checksum = "c420bbc064623934620b5ab2dc0cf96451b34163329e82f95e7fa1b7b99a6ac8"
 dependencies = [
  "byteorder",
  "memmap",
+ "parking_lot 0.9.0",
  "rustc-hash",
 ]
 
@@ -2072,9 +2039,9 @@
 
 [[package]]
 name = "memmap"
-version = "0.6.2"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
+checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
 dependencies = [
  "libc",
  "winapi 0.3.8",
@@ -2082,12 +2049,6 @@
 
 [[package]]
 name = "memoffset"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
-
-[[package]]
-name = "memoffset"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
@@ -2213,6 +2174,7 @@
  "rand 0.7.0",
  "rustc-workspace-hack",
  "rustc_version",
+ "serde",
  "shell-escape",
  "vergen",
 ]
@@ -2575,9 +2537,9 @@
 
 [[package]]
 name = "polonius-engine"
-version = "0.10.0"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50fa9dbfd0d3d60594da338cfe6f94028433eecae4b11b7e83fd99759227bbfe"
+checksum = "1e478d7c38eb785c6416cbe58df12aa55d7aefa3759b6d3e044b2ed03f423cec"
 dependencies = [
  "datafrog",
  "log",
@@ -2634,7 +2596,7 @@
 dependencies = [
  "proc-macro2 1.0.3",
  "quote 1.0.2",
- "syn 1.0.5",
+ "syn 1.0.11",
 ]
 
 [[package]]
@@ -2745,9 +2707,9 @@
 
 [[package]]
 name = "racer"
-version = "2.1.28"
+version = "2.1.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acc70369054bad4ad0c16a3f45cd73e0695361a3af35c7b465e619ac2674f064"
+checksum = "7a6d7ffceb4da3e0a29c18986f0469c209f4db3ab9f2ffe286eaa1104a3e5028"
 dependencies = [
  "bitflags",
  "clap",
@@ -3046,7 +3008,7 @@
 
 [[package]]
 name = "rls"
-version = "1.40.0"
+version = "1.41.0"
 dependencies = [
  "cargo",
  "cargo_metadata 0.8.0",
@@ -3195,8 +3157,8 @@
  "num_cpus",
  "parking_lot 0.9.0",
  "polonius-engine",
- "rustc-rayon 0.3.0",
- "rustc-rayon-core 0.3.0",
+ "rustc-rayon",
+ "rustc-rayon-core",
  "rustc_apfloat",
  "rustc_data_structures",
  "rustc_error_codes",
@@ -3216,9 +3178,9 @@
 
 [[package]]
 name = "rustc-ap-arena"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a623fd4805842e9bd0bb6e6dace63efede0ee22de4522a0b03b7c3d15a22f009"
+checksum = "7475f4c707269b56eb7144c53591e3cd6369a5aa1d66434829ea11df96d5e7e3"
 dependencies = [
  "rustc-ap-rustc_data_structures",
  "smallvec 0.6.10",
@@ -3226,15 +3188,15 @@
 
 [[package]]
 name = "rustc-ap-graphviz"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee549ade784b444ef10c0240c3487ed785aa65d711071f7984246b15329a17b6"
+checksum = "6e59a55520f140a70a3e0fad80a36e807caa85e9d7016167b91a5b521ea929be"
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca545744a5a9b42e3d0410d6290d40de96dd567253fe77f310c1de4afd213dd4"
+checksum = "6420857d5a088f680ec1ba736ffba4ee9c1964b0d397e6318f38d461f4f7d5cb"
 dependencies = [
  "cfg-if",
  "crossbeam-utils 0.6.5",
@@ -3248,17 +3210,17 @@
  "rustc-ap-rustc_index",
  "rustc-ap-serialize",
  "rustc-hash",
- "rustc-rayon 0.2.0",
- "rustc-rayon-core 0.2.0",
+ "rustc-rayon",
+ "rustc-rayon-core",
  "smallvec 0.6.10",
  "stable_deref_trait",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6967a41ed38ef4bce0f559fe9a4801d8ba12ac032f40a12a55e72f79d52c9bb"
+checksum = "8abfca0960131262254a91d02ff4903526a261ede730d7a2c75b4234c867cdc0"
 dependencies = [
  "annotate-snippets",
  "atty",
@@ -3273,9 +3235,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_index"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "457a5c204ae2fdaa5bdb5b196e58ca59896870d80445fe423063c9453496e3ea"
+checksum = "5a395509dcb90a92c1479c085639594624e06b4ab3fc7c1b795b46a61f2d4f65"
 dependencies = [
  "rustc-ap-serialize",
  "smallvec 0.6.10",
@@ -3283,31 +3245,31 @@
 
 [[package]]
 name = "rustc-ap-rustc_lexer"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed0c064676f8a08e42a36b0d4e4a102465fb0f4b75e11436cb7f66d2c3fa7139"
+checksum = "64eac8a0e6efb8f55292aa24be0208c7c0538236c613e79952fd1fa3d54bcf8e"
 dependencies = [
  "unicode-xid 0.2.0",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_macros"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2d77e46159c5288c585decbcdc9d742889c65e307c31e104c7a36d63fe1f5d0"
+checksum = "f99795e8be4877e9e05d59f201e1740c1cf673364655def5848606d9e25b75af"
 dependencies = [
  "itertools 0.8.0",
- "proc-macro2 0.4.30",
- "quote 0.6.12",
- "syn 0.15.35",
- "synstructure 0.10.2",
+ "proc-macro2 1.0.3",
+ "quote 1.0.2",
+ "syn 1.0.11",
+ "synstructure 0.12.1",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86ca895350b0de14d064b499168c93fa183958d5462eb042c927d93623e41ec1"
+checksum = "f22e21fdd8e1c0030f507158fa79b9f1e080e6241aba994d0f97c14a0a07a826"
 dependencies = [
  "bitflags",
  "log",
@@ -3319,9 +3281,9 @@
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92679240e86f4583cc05f8dcf6439bdab87bac9e6555718469176de9bd52ba20"
+checksum = "bb1cd6ef5135408d62559866e79986ca261f4c1333253d500e5e66fe66d1432e"
 dependencies = [
  "indexmap",
  "smallvec 0.6.10",
@@ -3329,9 +3291,9 @@
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a0c30f8e38c847dbfd9e2f1e472ab06d0bd0a23ab53ae4c5a44912842ce834e"
+checksum = "61fc1c901d2cbd24cae95d7bc5a58aa7661ec3dc5320c78c32830a52a685c33c"
 dependencies = [
  "bitflags",
  "lazy_static 1.3.0",
@@ -3349,9 +3311,9 @@
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "606.0.0"
+version = "610.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bdaa0fb40143b4b878256ac4e2b498885daafc269502504d91929eab4744bf4"
+checksum = "230534f638255853bb9f13987537e00a818435a0cc54b68d97221b6822c8f1bc"
 dependencies = [
  "cfg-if",
  "rustc-ap-arena",
@@ -3394,36 +3356,13 @@
 
 [[package]]
 name = "rustc-rayon"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363"
-dependencies = [
- "crossbeam-deque 0.2.0",
- "either",
- "rustc-rayon-core 0.2.0",
-]
-
-[[package]]
-name = "rustc-rayon"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a"
 dependencies = [
  "crossbeam-deque 0.7.1",
  "either",
- "rustc-rayon-core 0.3.0",
-]
-
-[[package]]
-name = "rustc-rayon-core"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543"
-dependencies = [
- "crossbeam-deque 0.2.0",
- "lazy_static 1.3.0",
- "libc",
- "num_cpus",
+ "rustc-rayon-core",
 ]
 
 [[package]]
@@ -3496,7 +3435,27 @@
 name = "rustc_codegen_llvm"
 version = "0.0.0"
 dependencies = [
+ "bitflags",
+ "flate2",
+ "libc",
+ "log",
+ "rustc",
+ "rustc-demangle",
+ "rustc_codegen_ssa",
+ "rustc_codegen_utils",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_feature",
+ "rustc_fs_util",
+ "rustc_incremental",
+ "rustc_index",
  "rustc_llvm",
+ "rustc_session",
+ "rustc_target",
+ "smallvec 0.6.10",
+ "syntax",
+ "syntax_expand",
+ "syntax_pos",
 ]
 
 [[package]]
@@ -3558,8 +3517,8 @@
  "measureme",
  "parking_lot 0.9.0",
  "rustc-hash",
- "rustc-rayon 0.3.0",
- "rustc-rayon-core 0.3.0",
+ "rustc-rayon",
+ "rustc-rayon-core",
  "rustc_index",
  "serialize",
  "smallvec 1.0.0",
@@ -3657,7 +3616,8 @@
  "log",
  "once_cell",
  "rustc",
- "rustc-rayon 0.3.0",
+ "rustc-rayon",
+ "rustc_codegen_llvm",
  "rustc_codegen_ssa",
  "rustc_codegen_utils",
  "rustc_data_structures",
@@ -3712,6 +3672,7 @@
 dependencies = [
  "build_helper",
  "cc",
+ "libc",
 ]
 
 [[package]]
@@ -3732,7 +3693,7 @@
  "itertools 0.8.0",
  "proc-macro2 1.0.3",
  "quote 1.0.2",
- "syn 1.0.5",
+ "syn 1.0.11",
  "synstructure 0.12.1",
 ]
 
@@ -3806,7 +3767,6 @@
  "rustc_errors",
  "rustc_feature",
  "rustc_lexer",
- "rustc_target",
  "smallvec 1.0.0",
  "syntax",
  "syntax_pos",
@@ -3985,7 +3945,9 @@
 dependencies = [
  "minifier",
  "pulldown-cmark 0.5.3",
- "rustc-rayon 0.3.0",
+ "rustc-rayon",
+ "serde",
+ "serde_json",
  "tempfile",
 ]
 
@@ -4019,12 +3981,12 @@
  "proc-macro2 1.0.3",
  "quote 1.0.2",
  "serde",
- "syn 1.0.5",
+ "syn 1.0.11",
 ]
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.9"
+version = "1.4.11"
 dependencies = [
  "annotate-snippets",
  "bytecount",
@@ -4189,7 +4151,7 @@
 dependencies = [
  "proc-macro2 1.0.3",
  "quote 1.0.2",
- "syn 1.0.5",
+ "syn 1.0.11",
 ]
 
 [[package]]
@@ -4402,7 +4364,7 @@
  "proc-macro-error",
  "proc-macro2 1.0.3",
  "quote 1.0.2",
- "syn 1.0.5",
+ "syn 1.0.11",
 ]
 
 [[package]]
@@ -4436,9 +4398,9 @@
 
 [[package]]
 name = "syn"
-version = "1.0.5"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
+checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
 dependencies = [
  "proc-macro2 1.0.3",
  "quote 1.0.2",
@@ -4465,7 +4427,7 @@
 dependencies = [
  "proc-macro2 1.0.3",
  "quote 1.0.2",
- "syn 1.0.5",
+ "syn 1.0.11",
  "unicode-xid 0.2.0",
 ]
 
diff --git a/RELEASES.md b/RELEASES.md
index 5313987..5afc6f9 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,140 @@
+Version 1.40.0 (2019-12-19)
+===========================
+
+Language
+--------
+- [You can now use tuple `struct`s and tuple `enum` variant's constructors in
+  `const` contexts.][65188] e.g.
+
+  ```rust
+  pub struct Point(i32, i32);
+
+  const ORIGIN: Point = {
+      let constructor = Point;
+
+      constructor(0, 0)
+  };
+  ```
+
+- [You can now mark `struct`s, `enum`s, and `enum` variants with the `#[non_exhaustive]` attribute to
+  indicate that there may be variants or fields added in the future.][64639]
+  For example this requires adding a wild-card branch (`_ => {}`) to any match
+  statements on a non-exhaustive `enum`. [(RFC 2008)]
+- [You can now use function-like procedural macros in `extern` blocks and in
+  type positions.][63931] e.g. `type Generated = macro!();`
+- [Function-like and attribute procedural macros can now emit
+  `macro_rules!` items, so you can now have your macros generate macros.][64035]
+- [The `meta` pattern matcher in `macro_rules!` now correctly matches the modern
+  attribute syntax.][63674] For example `(#[$m:meta])` now matches `#[attr]`,
+  `#[attr{tokens}]`, `#[attr[tokens]]`, and `#[attr(tokens)]`.
+
+Compiler
+--------
+- [Added tier 3 support\* for the
+  `thumbv7neon-unknown-linux-musleabihf` target.][66103]
+- [Added tier 3 support for the
+  `aarch64-unknown-none-softfloat` target.][64589]
+- [Added tier 3 support for the `mips64-unknown-linux-muslabi64`, and
+  `mips64el-unknown-linux-muslabi64` targets.][65843]
+
+\* Refer to Rust's [platform support page][forge-platform-support] for more
+  information on Rust's tiered platform support.
+
+Libraries
+---------
+- [The `is_power_of_two` method on unsigned numeric types is now a `const` function.][65092]
+
+Stabilized APIs
+---------------
+- [`BTreeMap::get_key_value`]
+- [`HashMap::get_key_value`]
+- [`Option::as_deref_mut`]
+- [`Option::as_deref`]
+- [`Option::flatten`]
+- [`UdpSocket::peer_addr`]
+- [`f32::to_be_bytes`]
+- [`f32::to_le_bytes`]
+- [`f32::to_ne_bytes`]
+- [`f64::to_be_bytes`]
+- [`f64::to_le_bytes`]
+- [`f64::to_ne_bytes`]
+- [`f32::from_be_bytes`]
+- [`f32::from_le_bytes`]
+- [`f32::from_ne_bytes`]
+- [`f64::from_be_bytes`]
+- [`f64::from_le_bytes`]
+- [`f64::from_ne_bytes`]
+- [`mem::take`]
+- [`slice::repeat`]
+- [`todo!`]
+
+Cargo
+-----
+- [Cargo will now always display warnings, rather than only on
+  fresh builds.][cargo/7450]
+- [Feature flags (except `--all-features`) passed to a virtual workspace will
+  now produce an error.][cargo/7507] Previously these flags were ignored.
+- [You can now publish `dev-dependencies` without including
+  a `version`.][cargo/7333]
+
+Misc
+----
+- [You can now specify the `#[cfg(doctest)]` attribute to include an item only
+  when running documentation tests with `rustdoc`.][63803]
+
+Compatibility Notes
+-------------------
+- [As previously announced, any previous NLL warnings in the 2015 edition are
+  now hard errors.][64221]
+- [The `include!` macro will now warn if it failed to include the
+  entire file.][64284] The `include!` macro unintentionally only includes the
+  first _expression_ in a file, and this can be unintuitive. This will become
+  either a hard error in a future release, or the behavior may be fixed to include all expressions as expected.
+- [Using `#[inline]` on function prototypes and consts now emits a warning under
+  `unused_attribute` lint.][65294] Using `#[inline]` anywhere else inside traits
+  or `extern` blocks now correctly emits a hard error.
+  
+[65294]: https://github.com/rust-lang/rust/pull/65294/
+[66103]: https://github.com/rust-lang/rust/pull/66103/
+[65843]: https://github.com/rust-lang/rust/pull/65843/
+[65188]: https://github.com/rust-lang/rust/pull/65188/
+[65092]: https://github.com/rust-lang/rust/pull/65092/
+[64589]: https://github.com/rust-lang/rust/pull/64589/
+[64639]: https://github.com/rust-lang/rust/pull/64639/
+[64221]: https://github.com/rust-lang/rust/pull/64221/
+[64284]: https://github.com/rust-lang/rust/pull/64284/
+[63931]: https://github.com/rust-lang/rust/pull/63931/
+[64035]: https://github.com/rust-lang/rust/pull/64035/
+[63674]: https://github.com/rust-lang/rust/pull/63674/
+[63803]: https://github.com/rust-lang/rust/pull/63803/
+[cargo/7450]: https://github.com/rust-lang/cargo/pull/7450/
+[cargo/7507]: https://github.com/rust-lang/cargo/pull/7507/
+[cargo/7525]: https://github.com/rust-lang/cargo/pull/7525/
+[cargo/7333]: https://github.com/rust-lang/cargo/pull/7333/
+[(rfc 2008)]: https://rust-lang.github.io/rfcs/2008-non-exhaustive.html
+[`f32::to_be_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_be_bytes
+[`f32::to_le_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_le_bytes
+[`f32::to_ne_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_ne_bytes
+[`f64::to_be_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.to_be_bytes
+[`f64::to_le_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.to_le_bytes
+[`f64::to_ne_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.to_ne_bytes
+[`f32::from_be_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.from_be_bytes
+[`f32::from_le_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.from_le_bytes
+[`f32::from_ne_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.from_ne_bytes
+[`f64::from_be_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.from_be_bytes
+[`f64::from_le_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.from_le_bytes
+[`f64::from_ne_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.from_ne_bytes
+[`option::flatten`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.flatten
+[`option::as_deref`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_deref
+[`option::as_deref_mut`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_deref_mut
+[`hashmap::get_key_value`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get_key_value
+[`btreemap::get_key_value`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.get_key_value
+[`slice::repeat`]: https://doc.rust-lang.org/std/primitive.slice.html#method.repeat
+[`mem::take`]: https://doc.rust-lang.org/std/mem/fn.take.html
+[`udpsocket::peer_addr`]: https://doc.rust-lang.org/std/net/struct.UdpSocket.html#method.peer_addr
+[`todo!`]: https://doc.rust-lang.org/std/macro.todo.html
+
+
 Version 1.39.0 (2019-11-07)
 ===========================
 
diff --git a/config.toml.example b/config.toml.example
index e832570..5152a6c 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -379,9 +379,6 @@
 # and currently the only standard option supported is `"llvm"`
 #codegen-backends = ["llvm"]
 
-# This is the name of the directory in which codegen backends will get installed
-#codegen-backends-dir = "codegen-backends"
-
 # Indicates whether LLD will be compiled and made available in the sysroot for
 # rustc to execute.
 #lld = false
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 99b8ddf..8b0ad16 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -339,7 +339,6 @@
             Kind::Build => describe!(
                 compile::Std,
                 compile::Rustc,
-                compile::CodegenBackend,
                 compile::StartupObjects,
                 tool::BuildManifest,
                 tool::Rustbook,
@@ -364,10 +363,10 @@
             Kind::Check | Kind::Clippy | Kind::Fix => describe!(
                 check::Std,
                 check::Rustc,
-                check::CodegenBackend,
                 check::Rustdoc
             ),
             Kind::Test => describe!(
+                crate::toolstate::ToolStateCheck,
                 test::Tidy,
                 test::Ui,
                 test::CompileFail,
@@ -631,11 +630,6 @@
         self.ensure(Libdir { compiler, target })
     }
 
-    pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
-        self.sysroot_libdir(compiler, compiler.host)
-            .with_file_name(self.config.rust_codegen_backends_dir.clone())
-    }
-
     /// Returns the compiler's libdir where it stores the dynamic libraries that
     /// it itself links against.
     ///
@@ -706,15 +700,6 @@
         }
     }
 
-    /// Gets the paths to all of the compiler's codegen backends.
-    fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = PathBuf> {
-        fs::read_dir(self.sysroot_codegen_backends(compiler))
-            .into_iter()
-            .flatten()
-            .filter_map(Result::ok)
-            .map(|entry| entry.path())
-    }
-
     pub fn rustdoc(&self, compiler: Compiler) -> PathBuf {
         self.ensure(tool::Rustdoc { compiler })
     }
@@ -758,12 +743,6 @@
         let mut cargo = Command::new(&self.initial_cargo);
         let out_dir = self.stage_out(compiler, mode);
 
-        // Codegen backends are not yet tracked by -Zbinary-dep-depinfo,
-        // so we need to explicitly clear out if they've been updated.
-        for backend in self.codegen_backends(compiler) {
-            self.clear_if_dirty(&out_dir, &backend);
-        }
-
         if cmd == "doc" || cmd == "rustdoc" {
             let my_out = match mode {
                 // This is the intended out directory for compiler documentation.
@@ -980,7 +959,7 @@
         // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it
         // fun to pass a flag to a tool to pass a flag to pass a flag to a tool
         // to change a flag in a binary?
-        if self.config.rust_rpath {
+        if self.config.rust_rpath && util::use_host_linker(&target) {
             let rpath = if target.contains("apple") {
 
                 // Note that we need to take one extra step on macOS to also pass
@@ -990,10 +969,7 @@
                 // flesh out rpath support more fully in the future.
                 rustflags.arg("-Zosx-rpath-install-name");
                 Some("-Wl,-rpath,@loader_path/../lib")
-            } else if !target.contains("windows") &&
-                      !target.contains("wasm32") &&
-                      !target.contains("emscripten") &&
-                      !target.contains("fuchsia") {
+            } else if !target.contains("windows") {
                 Some("-Wl,-rpath,$ORIGIN/../lib")
             } else {
                 None
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 2bb90fd..b9d97fb 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -363,6 +363,10 @@
                 compiler: Compiler { host: a, stage: 1 },
                 target: b,
             },
+            compile::Std {
+                compiler: Compiler { host: a, stage: 2 },
+                target: b,
+            },
         ]
     );
     assert_eq!(
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index df1c725..f5c427d 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -1,11 +1,10 @@
 //! Implementation of compiling the compiler and standard library, in "check"-based modes.
 
-use crate::compile::{run_cargo, std_cargo, rustc_cargo, rustc_cargo_env,
-                     add_to_sysroot};
+use crate::compile::{run_cargo, std_cargo, rustc_cargo, add_to_sysroot};
 use crate::builder::{RunConfig, Builder, Kind, ShouldRun, Step};
 use crate::tool::{prepare_tool_cargo, SourceType};
 use crate::{Compiler, Mode};
-use crate::cache::{INTERNER, Interned};
+use crate::cache::Interned;
 use std::path::PathBuf;
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -97,7 +96,7 @@
 
         let mut cargo = builder.cargo(compiler, Mode::Rustc, target,
             cargo_subcommand(builder.kind));
-        rustc_cargo(builder, &mut cargo);
+        rustc_cargo(builder, &mut cargo, target);
 
         builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
         run_cargo(builder,
@@ -114,55 +113,6 @@
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct CodegenBackend {
-    pub target: Interned<String>,
-    pub backend: Interned<String>,
-}
-
-impl Step for CodegenBackend {
-    type Output = ();
-    const ONLY_HOSTS: bool = true;
-    const DEFAULT: bool = true;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.all_krates("rustc_codegen_llvm")
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        let backend = run.builder.config.rust_codegen_backends.get(0);
-        let backend = backend.cloned().unwrap_or_else(|| {
-            INTERNER.intern_str("llvm")
-        });
-        run.builder.ensure(CodegenBackend {
-            target: run.target,
-            backend,
-        });
-    }
-
-    fn run(self, builder: &Builder<'_>) {
-        let compiler = builder.compiler(0, builder.config.build);
-        let target = self.target;
-        let backend = self.backend;
-
-        builder.ensure(Rustc { target });
-
-        let mut cargo = builder.cargo(compiler, Mode::Codegen, target,
-            cargo_subcommand(builder.kind));
-        cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
-        rustc_cargo_env(builder, &mut cargo);
-
-        // We won't build LLVM if it's not available, as it shouldn't affect `check`.
-
-        run_cargo(builder,
-                  cargo,
-                  args(builder.kind),
-                  &codegen_backend_stamp(builder, compiler, target, backend),
-                  vec![],
-                  true);
-    }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Rustdoc {
     pub target: Interned<String>,
 }
@@ -231,16 +181,6 @@
     builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
 }
 
-/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
-/// compiler for the specified target and backend.
-fn codegen_backend_stamp(builder: &Builder<'_>,
-                         compiler: Compiler,
-                         target: Interned<String>,
-                         backend: Interned<String>) -> PathBuf {
-    builder.cargo_out(compiler, Mode::Codegen, target)
-         .join(format!(".librustc_codegen_llvm-{}-check.stamp", backend))
-}
-
 /// Cargo's output path for rustdoc in a given stage, compiled by a particular
 /// compiler for the specified target.
 pub fn rustdoc_stamp(
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index f686dfe..baf9aab 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -27,7 +27,7 @@
 use crate::native;
 
 use crate::cache::{INTERNER, Interned};
-use crate::builder::{Step, RunConfig, ShouldRun, Builder};
+use crate::builder::{Step, RunConfig, ShouldRun, Builder, Kind};
 
 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Std {
@@ -445,7 +445,7 @@
         });
 
         let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build");
-        rustc_cargo(builder, &mut cargo);
+        rustc_cargo(builder, &mut cargo, target);
 
         builder.info(&format!("Building stage{} compiler artifacts ({} -> {})",
                  compiler.stage, &compiler.host, target));
@@ -456,6 +456,44 @@
                   vec![],
                   false);
 
+        // We used to build librustc_codegen_llvm as a separate step,
+        // which produced a dylib that the compiler would dlopen() at runtime.
+        // This meant that we only needed to make sure that libLLVM.so was
+        // installed by the time we went to run a tool using it - since
+        // librustc_codegen_llvm was effectively a standalone artifact,
+        // other crates were completely oblivious to its dependency
+        // on `libLLVM.so` during build time.
+        //
+        // However, librustc_codegen_llvm is now built as an ordinary
+        // crate during the same step as the rest of the compiler crates.
+        // This means that any crates depending on it will see the fact
+        // that it uses `libLLVM.so` as a native library, and will
+        // cause us to pass `-llibLLVM.so` to the linker when we link
+        // a binary.
+        //
+        // For `rustc` itself, this works out fine.
+        // During the `Assemble` step, we call `dist::maybe_install_llvm_dylib`
+        // to copy libLLVM.so into the `stage` directory. We then link
+        // the compiler binary, which will find `libLLVM.so` in the correct place.
+        //
+        // However, this is insufficient for tools that are build against stage0
+        // (e.g. stage1 rustdoc). Since `Assemble` for stage0 doesn't actually do anything,
+        // we won't have `libLLVM.so` in the stage0 sysroot. In the past, this wasn't
+        // a problem - we would copy the tool binary into its correct stage directory
+        // (e.g. stage1 for a stage1 rustdoc built against a stage0 compiler).
+        // Since libLLVM.so wasn't resolved until runtime, it was fine for it to
+        // not exist while we were building it.
+        //
+        // To ensure that we can still build stage1 tools against a stage0 compiler,
+        // we explicitly copy libLLVM.so into the stage0 sysroot when building
+        // the stage0 compiler. This ensures that tools built against stage0
+        // will see libLLVM.so at build time, making the linker happy.
+        if compiler.stage == 0 {
+            builder.info(&format!("Installing libLLVM.so to stage 0 ({})", compiler.host));
+            let sysroot = builder.sysroot(compiler);
+            dist::maybe_install_llvm_dylib(builder, compiler.host, &sysroot);
+        }
+
         builder.ensure(RustcLink {
             compiler: builder.compiler(compiler.stage, builder.config.build),
             target_compiler: compiler,
@@ -464,21 +502,20 @@
     }
 }
 
-pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo) {
+pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) {
     cargo.arg("--features").arg(builder.rustc_features())
          .arg("--manifest-path")
          .arg(builder.src.join("src/rustc/Cargo.toml"));
-    rustc_cargo_env(builder, cargo);
+    rustc_cargo_env(builder, cargo, target);
 }
 
-pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo) {
+pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) {
     // Set some configuration variables picked up by build scripts and
     // the compiler alike
     cargo.env("CFG_RELEASE", builder.rust_release())
          .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
          .env("CFG_VERSION", builder.rust_version())
-         .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default())
-         .env("CFG_CODEGEN_BACKENDS_DIR", &builder.config.rust_codegen_backends_dir);
+         .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default());
 
     let libdir_relative = builder.config.libdir_relative().unwrap_or(Path::new("lib"));
     cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
@@ -501,6 +538,49 @@
     if builder.config.rust_verify_llvm_ir {
         cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
     }
+
+    // Pass down configuration from the LLVM build into the build of
+    // librustc_llvm and librustc_codegen_llvm.
+    //
+    // Note that this is disabled if LLVM itself is disabled or we're in a check
+    // build, where if we're in a check build there's no need to build all of
+    // LLVM and such.
+    if builder.config.llvm_enabled() && builder.kind != Kind::Check {
+        if builder.is_rust_llvm(target) {
+            cargo.env("LLVM_RUSTLLVM", "1");
+        }
+        let llvm_config = builder.ensure(native::Llvm { target });
+        cargo.env("LLVM_CONFIG", &llvm_config);
+        let target_config = builder.config.target_config.get(&target);
+        if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
+            cargo.env("CFG_LLVM_ROOT", s);
+        }
+        // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm.
+        if let Some(ref s) = builder.config.llvm_ldflags {
+            cargo.env("LLVM_LINKER_FLAGS", s);
+        }
+        // Building with a static libstdc++ is only supported on linux right now,
+        // not for MSVC or macOS
+        if builder.config.llvm_static_stdcpp &&
+           !target.contains("freebsd") &&
+           !target.contains("windows") &&
+           !target.contains("apple") {
+            let file = compiler_file(builder,
+                                     builder.cxx(target).unwrap(),
+                                     target,
+                                     "libstdc++.a");
+            cargo.env("LLVM_STATIC_STDCPP", file);
+        }
+        if builder.config.llvm_link_shared || builder.config.llvm_thin_lto {
+            cargo.env("LLVM_LINK_SHARED", "1");
+        }
+        if builder.config.llvm_use_libcxx {
+            cargo.env("LLVM_USE_LIBCXX", "1");
+        }
+        if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo {
+            cargo.env("LLVM_NDEBUG", "1");
+        }
+    }
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -537,215 +617,6 @@
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct CodegenBackend {
-    pub compiler: Compiler,
-    pub target: Interned<String>,
-    pub backend: Interned<String>,
-}
-
-impl Step for CodegenBackend {
-    type Output = ();
-    const ONLY_HOSTS: bool = true;
-    const DEFAULT: bool = true;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.all_krates("rustc_codegen_llvm")
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        let backend = run.builder.config.rust_codegen_backends.get(0);
-        let backend = backend.cloned().unwrap_or_else(|| {
-            INTERNER.intern_str("llvm")
-        });
-        run.builder.ensure(CodegenBackend {
-            compiler: run.builder.compiler(run.builder.top_stage, run.host),
-            target: run.target,
-            backend,
-        });
-    }
-
-    fn run(self, builder: &Builder<'_>) {
-        let compiler = self.compiler;
-        let target = self.target;
-        let backend = self.backend;
-
-        builder.ensure(Rustc { compiler, target });
-
-        if builder.config.keep_stage.contains(&compiler.stage) {
-            builder.info("Warning: Using a potentially old codegen backend. \
-                This may not behave well.");
-            // Codegen backends are linked separately from this step today, so we don't do
-            // anything here.
-            return;
-        }
-
-        let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
-        if compiler_to_use != compiler {
-            builder.ensure(CodegenBackend {
-                compiler: compiler_to_use,
-                target,
-                backend,
-            });
-            return;
-        }
-
-        let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
-
-        let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build");
-        cargo.arg("--manifest-path")
-            .arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
-        rustc_cargo_env(builder, &mut cargo);
-
-        let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
-        cargo.arg("--features").arg(features);
-
-        let tmp_stamp = out_dir.join(".tmp.stamp");
-
-        let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false);
-        if builder.config.dry_run {
-            return;
-        }
-        let mut files = files.into_iter()
-            .filter(|f| {
-                let filename = f.file_name().unwrap().to_str().unwrap();
-                is_dylib(filename) && filename.contains("rustc_codegen_llvm-")
-            });
-        let codegen_backend = match files.next() {
-            Some(f) => f,
-            None => panic!("no dylibs built for codegen backend?"),
-        };
-        if let Some(f) = files.next() {
-            panic!("codegen backend built two dylibs:\n{}\n{}",
-                   codegen_backend.display(),
-                   f.display());
-        }
-        let stamp = codegen_backend_stamp(builder, compiler, target, backend);
-        let codegen_backend = codegen_backend.to_str().unwrap();
-        t!(fs::write(&stamp, &codegen_backend));
-    }
-}
-
-pub fn build_codegen_backend(builder: &Builder<'_>,
-                             cargo: &mut Cargo,
-                             compiler: &Compiler,
-                             target: Interned<String>,
-                             backend: Interned<String>) -> String {
-    match &*backend {
-        "llvm" => {
-            // Build LLVM for our target. This will implicitly build the
-            // host LLVM if necessary.
-            let llvm_config = builder.ensure(native::Llvm {
-                target,
-            });
-
-            builder.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})",
-                     compiler.stage, &compiler.host, target, backend));
-
-            // Pass down configuration from the LLVM build into the build of
-            // librustc_llvm and librustc_codegen_llvm.
-            if builder.is_rust_llvm(target) {
-                cargo.env("LLVM_RUSTLLVM", "1");
-            }
-
-            cargo.env("LLVM_CONFIG", &llvm_config);
-            let target_config = builder.config.target_config.get(&target);
-            if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
-                cargo.env("CFG_LLVM_ROOT", s);
-            }
-            // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm.
-            if let Some(ref s) = builder.config.llvm_ldflags {
-                cargo.env("LLVM_LINKER_FLAGS", s);
-            }
-            // Building with a static libstdc++ is only supported on linux and mingw right now,
-            // not for MSVC or macOS
-            if builder.config.llvm_static_stdcpp &&
-               !target.contains("freebsd") &&
-               !target.contains("msvc") &&
-               !target.contains("apple") {
-                let file = compiler_file(builder,
-                                         builder.cxx(target).unwrap(),
-                                         target,
-                                         "libstdc++.a");
-                cargo.env("LLVM_STATIC_STDCPP", file);
-            }
-            if builder.config.llvm_link_shared || builder.config.llvm_thin_lto {
-                cargo.env("LLVM_LINK_SHARED", "1");
-            }
-            if builder.config.llvm_use_libcxx {
-                cargo.env("LLVM_USE_LIBCXX", "1");
-            }
-            if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo {
-                cargo.env("LLVM_NDEBUG", "1");
-            }
-        }
-        _ => panic!("unknown backend: {}", backend),
-    }
-    String::new()
-}
-
-/// Creates the `codegen-backends` folder for a compiler that's about to be
-/// assembled as a complete compiler.
-///
-/// This will take the codegen artifacts produced by `compiler` and link them
-/// into an appropriate location for `target_compiler` to be a functional
-/// compiler.
-fn copy_codegen_backends_to_sysroot(builder: &Builder<'_>,
-                                    compiler: Compiler,
-                                    target_compiler: Compiler) {
-    let target = target_compiler.host;
-
-    // Note that this step is different than all the other `*Link` steps in
-    // that it's not assembling a bunch of libraries but rather is primarily
-    // moving the codegen backend into place. The codegen backend of rustc is
-    // not linked into the main compiler by default but is rather dynamically
-    // selected at runtime for inclusion.
-    //
-    // Here we're looking for the output dylib of the `CodegenBackend` step and
-    // we're copying that into the `codegen-backends` folder.
-    let dst = builder.sysroot_codegen_backends(target_compiler);
-    t!(fs::create_dir_all(&dst));
-
-    if builder.config.dry_run {
-        return;
-    }
-
-    for backend in builder.config.rust_codegen_backends.iter() {
-        let stamp = codegen_backend_stamp(builder, compiler, target, *backend);
-        let dylib = t!(fs::read_to_string(&stamp));
-        let file = Path::new(&dylib);
-        let filename = file.file_name().unwrap().to_str().unwrap();
-        // change `librustc_codegen_llvm-xxxxxx.so` to `librustc_codegen_llvm-llvm.so`
-        let target_filename = {
-            let dash = filename.find('-').unwrap();
-            let dot = filename.find('.').unwrap();
-            format!("{}-{}{}",
-                    &filename[..dash],
-                    backend,
-                    &filename[dot..])
-        };
-        builder.copy(&file, &dst.join(target_filename));
-    }
-}
-
-fn copy_lld_to_sysroot(builder: &Builder<'_>,
-                       target_compiler: Compiler,
-                       lld_install_root: &Path) {
-    let target = target_compiler.host;
-
-    let dst = builder.sysroot_libdir(target_compiler, target)
-        .parent()
-        .unwrap()
-        .join("bin");
-    t!(fs::create_dir_all(&dst));
-
-    let src_exe = exe("lld", &target);
-    let dst_exe = exe("rust-lld", &target);
-    // we prepend this bin directory to the user PATH when linking Rust binaries. To
-    // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
-    builder.copy(&lld_install_root.join("bin").join(&src_exe), &dst.join(&dst_exe));
-}
-
 /// Cargo's output path for the standard library in a given stage, compiled
 /// by a particular compiler for the specified target.
 pub fn libstd_stamp(
@@ -766,16 +637,6 @@
     builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp")
 }
 
-/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
-/// compiler for the specified target and backend.
-fn codegen_backend_stamp(builder: &Builder<'_>,
-                         compiler: Compiler,
-                         target: Interned<String>,
-                         backend: Interned<String>) -> PathBuf {
-    builder.cargo_out(compiler, Mode::Codegen, target)
-        .join(format!(".librustc_codegen_llvm-{}.stamp", backend))
-}
-
 pub fn compiler_file(
     builder: &Builder<'_>,
     compiler: &Path,
@@ -879,13 +740,6 @@
             compiler: build_compiler,
             target: target_compiler.host,
         });
-        for &backend in builder.config.rust_codegen_backends.iter() {
-            builder.ensure(CodegenBackend {
-                compiler: build_compiler,
-                target: target_compiler.host,
-                backend,
-            });
-        }
 
         let lld_install = if builder.config.lld_enabled {
             Some(builder.ensure(native::Lld {
@@ -911,13 +765,19 @@
             }
         }
 
-        copy_codegen_backends_to_sysroot(builder,
-                                         build_compiler,
-                                         target_compiler);
+        let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host);
         if let Some(lld_install) = lld_install {
-            copy_lld_to_sysroot(builder, target_compiler, &lld_install);
+            let src_exe = exe("lld", &target_compiler.host);
+            let dst_exe = exe("rust-lld", &target_compiler.host);
+            // we prepend this bin directory to the user PATH when linking Rust binaries. To
+            // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
+            let dst = libdir.parent().unwrap().join("bin");
+            t!(fs::create_dir_all(&dst));
+            builder.copy(&lld_install.join("bin").join(&src_exe), &dst.join(&dst_exe));
         }
 
+        // Ensure that `libLLVM.so` ends up in the newly build compiler directory,
+        // so that it can be found when the newly built `rustc` is run.
         dist::maybe_install_llvm_dylib(builder, target_compiler.host, &sysroot);
 
         // Link the compiler binary itself into place
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 0c03b95..5f2ef01 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -105,7 +105,6 @@
     pub rust_optimize_tests: bool,
     pub rust_dist_src: bool,
     pub rust_codegen_backends: Vec<Interned<String>>,
-    pub rust_codegen_backends_dir: String,
     pub rust_verify_llvm_ir: bool,
     pub rust_remap_debuginfo: bool,
 
@@ -316,7 +315,6 @@
     dist_src: Option<bool>,
     save_toolstates: Option<String>,
     codegen_backends: Option<Vec<String>>,
-    codegen_backends_dir: Option<String>,
     lld: Option<bool>,
     llvm_tools: Option<bool>,
     lldb: Option<bool>,
@@ -372,7 +370,6 @@
         config.ignore_git = false;
         config.rust_dist_src = true;
         config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
-        config.rust_codegen_backends_dir = "codegen-backends".to_owned();
         config.deny_warnings = true;
         config.missing_tools = false;
 
@@ -575,8 +572,6 @@
                     .collect();
             }
 
-            set(&mut config.rust_codegen_backends_dir, rust.codegen_backends_dir.clone());
-
             config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
             config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
         }
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index d0c9e0d..0253394 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -498,16 +498,6 @@
                 }
             }
 
-            // Copy over the codegen backends
-            let backends_src = builder.sysroot_codegen_backends(compiler);
-            let backends_rel = backends_src.strip_prefix(&src).unwrap()
-                .strip_prefix(builder.sysroot_libdir_relative(compiler)).unwrap();
-            // Don't use custom libdir here because ^lib/ will be resolved again with installer
-            let backends_dst = image.join("lib").join(&backends_rel);
-
-            t!(fs::create_dir_all(&backends_dst));
-            builder.cp_r(&backends_src, &backends_dst);
-
             // Copy libLLVM.so to the lib dir as well, if needed. While not
             // technically needed by rustc itself it's needed by lots of other
             // components like the llvm tools and LLD. LLD is included below and
@@ -2134,6 +2124,10 @@
 
 // Maybe add libLLVM.so to the lib-dir. It will only have been built if
 // LLVM tools are linked dynamically.
+//
+// We add this to both the libdir of the rustc binary itself (for it to load at
+// runtime) and also to the target directory so it can find it at link-time.
+//
 // Note: This function does no yet support Windows but we also don't support
 //       linking LLVM tools dynamically on Windows yet.
 pub fn maybe_install_llvm_dylib(builder: &Builder<'_>,
@@ -2142,13 +2136,19 @@
     let src_libdir = builder
         .llvm_out(target)
         .join("lib");
-    let dst_libdir = sysroot.join("lib/rustlib").join(&*target).join("lib");
-    t!(fs::create_dir_all(&dst_libdir));
+    let dst_libdir1 = sysroot.join("lib/rustlib").join(&*target).join("lib");
+    let dst_libdir2 = sysroot.join(builder.sysroot_libdir_relative(Compiler {
+        stage: 1,
+        host: target,
+    }));
+    t!(fs::create_dir_all(&dst_libdir1));
+    t!(fs::create_dir_all(&dst_libdir2));
 
     if target.contains("apple-darwin") {
         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
         if llvm_dylib_path.exists() {
-            builder.install(&llvm_dylib_path, &dst_libdir, 0o644);
+            builder.install(&llvm_dylib_path, &dst_libdir1, 0o644);
+            builder.install(&llvm_dylib_path, &dst_libdir2, 0o644);
         }
         return
     }
@@ -2164,7 +2164,8 @@
         });
 
 
-        builder.install(&llvm_dylib_path, &dst_libdir, 0o644);
+        builder.install(&llvm_dylib_path, &dst_libdir1, 0o644);
+        builder.install(&llvm_dylib_path, &dst_libdir2, 0o644);
     }
 }
 
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 4ee8cd2..608cee0 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -433,7 +433,7 @@
         builder.info(&format!("Documenting stage{} std ({})", stage, target));
         let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
-        let compiler = builder.compiler_for(stage, builder.config.build, target);
+        let compiler = builder.compiler(stage, builder.config.build);
 
         builder.ensure(compile::Std { compiler, target });
         let out_dir = builder.stage_out(compiler, Mode::Std)
@@ -541,7 +541,7 @@
         // Build cargo command.
         let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
         cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden");
-        compile::rustc_cargo(builder, &mut cargo);
+        compile::rustc_cargo(builder, &mut cargo, target);
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
         cargo.arg("--no-deps");
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 39d7ea9..080bef6 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -169,7 +169,6 @@
 pub use crate::config::Config;
 use crate::flags::Subcommand;
 use crate::cache::{Interned, INTERNER};
-use crate::toolstate::ToolState;
 
 const LLVM_TOOLS: &[&str] = &[
     "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility
@@ -501,6 +500,9 @@
         if self.config.jemalloc {
             features.push_str("jemalloc");
         }
+        if self.config.llvm_enabled() {
+            features.push_str(" llvm");
+        }
         features
     }
 
@@ -806,11 +808,8 @@
                                                        .and_then(|c| c.linker.as_ref()) {
             Some(linker)
         } else if target != self.config.build &&
-                  !target.contains("msvc") &&
-                  !target.contains("emscripten") &&
-                  !target.contains("wasm32") &&
-                  !target.contains("nvptx") &&
-                  !target.contains("fuchsia") {
+                  util::use_host_linker(&target) &&
+                  !target.contains("msvc") {
             Some(self.cc(target))
         } else {
             None
@@ -1073,32 +1072,6 @@
         }
     }
 
-    /// Updates the actual toolstate of a tool.
-    ///
-    /// The toolstates are saved to the file specified by the key
-    /// `rust.save-toolstates` in `config.toml`. If unspecified, nothing will be
-    /// done. The file is updated immediately after this function completes.
-    pub fn save_toolstate(&self, tool: &str, state: ToolState) {
-        if let Some(ref path) = self.config.save_toolstates {
-            if let Some(parent) = path.parent() {
-                // Ensure the parent directory always exists
-                t!(std::fs::create_dir_all(parent));
-            }
-            let mut file = t!(fs::OpenOptions::new()
-                .create(true)
-                .read(true)
-                .write(true)
-                .open(path));
-
-            let mut current_toolstates: HashMap<Box<str>, ToolState> =
-                serde_json::from_reader(&mut file).unwrap_or_default();
-            current_toolstates.insert(tool.into(), state);
-            t!(file.seek(SeekFrom::Start(0)));
-            t!(file.set_len(0));
-            t!(serde_json::to_writer(file, &current_toolstates));
-        }
-    }
-
     fn in_tree_crates(&self, root: &str) -> Vec<&Crate> {
         let mut ret = Vec::new();
         let mut list = vec![INTERNER.intern_str(root)];
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index a858ed4..f3b2a73 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1773,7 +1773,7 @@
             }
             Mode::Rustc => {
                 builder.ensure(compile::Rustc { compiler, target });
-                compile::rustc_cargo(builder, &mut cargo);
+                compile::rustc_cargo(builder, &mut cargo, target);
             }
             _ => panic!("can only test libraries"),
         };
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index e86209b..a6d9ef3 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -1,4 +1,28 @@
 use serde::{Deserialize, Serialize};
+use build_helper::t;
+use std::time;
+use std::fs;
+use std::io::{Seek, SeekFrom};
+use std::collections::HashMap;
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use std::fmt;
+use std::process::Command;
+use std::path::PathBuf;
+use std::env;
+
+// Each cycle is 42 days long (6 weeks); the last week is 35..=42 then.
+const BETA_WEEK_START: u64 = 35;
+
+#[cfg(linux)]
+const OS: Option<&str> = Some("linux");
+
+#[cfg(windows)]
+const OS: Option<&str> = Some("windows");
+
+#[cfg(all(not(linux), not(windows)))]
+const OS: Option<&str> = None;
+
+type ToolstateData = HashMap<Box<str>, ToolState>;
 
 #[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
 #[serde(rename_all = "kebab-case")]
@@ -12,9 +36,392 @@
     BuildFail = 0,
 }
 
+impl fmt::Display for ToolState {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", match self {
+            ToolState::TestFail => "test-fail",
+            ToolState::TestPass => "test-pass",
+            ToolState::BuildFail => "build-fail",
+        })
+    }
+}
+
 impl Default for ToolState {
     fn default() -> Self {
         // err on the safe side
         ToolState::BuildFail
     }
 }
+
+/// Number of days after the last promotion of beta.
+/// Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens.
+/// The Wednesday after this has value 0.
+/// We track this value to prevent regressing tools in the last week of the 6-week cycle.
+fn days_since_beta_promotion() -> u64 {
+    let since_epoch = t!(time::SystemTime::UNIX_EPOCH.elapsed());
+    (since_epoch.as_secs() / 86400 - 20) % 42
+}
+
+// These tools must test-pass on the beta/stable channels.
+//
+// On the nightly channel, their build step must be attempted, but they may not
+// be able to build successfully.
+static STABLE_TOOLS: &[(&str, &str)] = &[
+    ("book", "src/doc/book"),
+    ("nomicon", "src/doc/nomicon"),
+    ("reference", "src/doc/reference"),
+    ("rust-by-example", "src/doc/rust-by-example"),
+    ("edition-guide", "src/doc/edition-guide"),
+    ("rls", "src/tools/rls"),
+    ("rustfmt", "src/tools/rustfmt"),
+    ("clippy-driver", "src/tools/clippy"),
+];
+
+// These tools are permitted to not build on the beta/stable channels.
+//
+// We do require that we checked whether they build or not on the tools builder,
+// though, as otherwise we will be unable to file an issue if they start
+// failing.
+static NIGHTLY_TOOLS: &[(&str, &str)] = &[
+    ("miri", "src/tools/miri"),
+    ("embedded-book", "src/doc/embedded-book"),
+    ("rustc-guide", "src/doc/rustc-guide"),
+];
+
+fn print_error(tool: &str, submodule: &str) {
+    eprintln!("");
+    eprintln!("We detected that this PR updated '{}', but its tests failed.", tool);
+    eprintln!("");
+    eprintln!("If you do intend to update '{}', please check the error messages above and", tool);
+    eprintln!("commit another update.");
+    eprintln!("");
+    eprintln!("If you do NOT intend to update '{}', please ensure you did not accidentally", tool);
+    eprintln!("change the submodule at '{}'. You may ask your reviewer for the", submodule);
+    eprintln!("proper steps.");
+    std::process::exit(3);
+}
+
+fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) {
+    // Changed files
+    let output = std::process::Command::new("git")
+        .arg("diff")
+        .arg("--name-status")
+        .arg("HEAD")
+        .arg("HEAD^")
+        .output();
+    let output = match output {
+        Ok(o) => o,
+        Err(e) => {
+            eprintln!("Failed to get changed files: {:?}", e);
+            std::process::exit(1);
+        }
+    };
+
+    let output = t!(String::from_utf8(output.stdout));
+
+    for (tool, submodule) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) {
+        let changed = output.lines().any(|l| {
+            l.starts_with("M") && l.ends_with(submodule)
+        });
+        eprintln!("Verifying status of {}...", tool);
+        if !changed {
+            continue;
+        }
+
+        eprintln!("This PR updated '{}', verifying if status is 'test-pass'...", submodule);
+        if toolstates[*tool] != ToolState::TestPass {
+            print_error(tool, submodule);
+        }
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct ToolStateCheck;
+
+impl Step for ToolStateCheck {
+    type Output = ();
+
+    /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
+    ///
+    /// This tool in `src/tools` will verify the validity of all our links in the
+    /// documentation to ensure we don't have a bunch of dead ones.
+    fn run(self, builder: &Builder<'_>) {
+        if builder.config.dry_run {
+            return;
+        }
+
+        let days_since_beta_promotion = days_since_beta_promotion();
+        let in_beta_week = days_since_beta_promotion >= BETA_WEEK_START;
+        let is_nightly = !(builder.config.channel == "beta" || builder.config.channel == "stable");
+        let toolstates = builder.toolstates();
+
+        let mut did_error = false;
+
+        for (tool, _) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) {
+            if !toolstates.contains_key(*tool) {
+                did_error = true;
+                eprintln!("error: Tool `{}` was not recorded in tool state.", tool);
+            }
+        }
+
+        if did_error {
+            std::process::exit(1);
+        }
+
+        check_changed_files(&toolstates);
+
+        for (tool, _) in STABLE_TOOLS.iter() {
+            let state = toolstates[*tool];
+
+            if state != ToolState::TestPass {
+                if !is_nightly {
+                    did_error = true;
+                    eprintln!("error: Tool `{}` should be test-pass but is {}", tool, state);
+                } else if in_beta_week {
+                    did_error = true;
+                    eprintln!("error: Tool `{}` should be test-pass but is {} during beta week.",
+                        tool, state);
+                }
+            }
+        }
+
+        if did_error {
+            std::process::exit(1);
+        }
+
+        if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() {
+            commit_toolstate_change(&toolstates, in_beta_week);
+        }
+    }
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("check-tools")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(ToolStateCheck);
+    }
+}
+
+impl Builder<'_> {
+    fn toolstates(&self) -> HashMap<Box<str>, ToolState> {
+        if let Some(ref path) = self.config.save_toolstates {
+            if let Some(parent) = path.parent() {
+                // Ensure the parent directory always exists
+                t!(std::fs::create_dir_all(parent));
+            }
+            let mut file = t!(fs::OpenOptions::new()
+                .create(true)
+                .write(true)
+                .read(true)
+                .open(path));
+
+            serde_json::from_reader(&mut file).unwrap_or_default()
+        } else {
+            Default::default()
+        }
+    }
+
+    /// Updates the actual toolstate of a tool.
+    ///
+    /// The toolstates are saved to the file specified by the key
+    /// `rust.save-toolstates` in `config.toml`. If unspecified, nothing will be
+    /// done. The file is updated immediately after this function completes.
+    pub fn save_toolstate(&self, tool: &str, state: ToolState) {
+        if let Some(ref path) = self.config.save_toolstates {
+            if let Some(parent) = path.parent() {
+                // Ensure the parent directory always exists
+                t!(std::fs::create_dir_all(parent));
+            }
+            let mut file = t!(fs::OpenOptions::new()
+                .create(true)
+                .read(true)
+                .write(true)
+                .open(path));
+
+            let mut current_toolstates: HashMap<Box<str>, ToolState> =
+                serde_json::from_reader(&mut file).unwrap_or_default();
+            current_toolstates.insert(tool.into(), state);
+            t!(file.seek(SeekFrom::Start(0)));
+            t!(file.set_len(0));
+            t!(serde_json::to_writer(file, &current_toolstates));
+        }
+    }
+}
+
+/// This function `commit_toolstate_change` provides functionality for pushing a change
+/// to the `rust-toolstate` repository.
+///
+/// The function relies on a GitHub bot user, which should have a Personal access
+/// token defined in the environment variable $TOOLSTATE_REPO_ACCESS_TOKEN. If for
+/// some reason you need to change the token, please update the Azure Pipelines
+/// variable group.
+///
+///   1. Generate a new Personal access token:
+///
+///       * Login to the bot account, and go to Settings -> Developer settings ->
+///           Personal access tokens
+///       * Click "Generate new token"
+///       * Enable the "public_repo" permission, then click "Generate token"
+///       * Copy the generated token (should be a 40-digit hexadecimal number).
+///           Save it somewhere secure, as the token would be gone once you leave
+///           the page.
+///
+///   2. Update the variable group in Azure Pipelines
+///
+///       * Ping a member of the infrastructure team to do this.
+///
+///   4. Replace the email address below if the bot account identity is changed
+///
+///       * See <https://help.github.com/articles/about-commit-email-addresses/>
+///           if a private email by GitHub is wanted.
+fn commit_toolstate_change(
+    current_toolstate: &ToolstateData,
+    in_beta_week: bool,
+) {
+    fn git_config(key: &str, value: &str) {
+        let status = Command::new("git").arg("config").arg("--global").arg(key).arg(value).status();
+        let success = match status {
+            Ok(s) => s.success(),
+            Err(_) => false,
+        };
+        if !success {
+            panic!("git config key={} value={} successful (status: {:?})", key, value, status);
+        }
+    }
+
+    // If changing anything here, then please check that src/ci/publish_toolstate.sh is up to date
+    // as well.
+    git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com");
+    git_config("user.name", "Rust Toolstate Update");
+    git_config("credential.helper", "store");
+
+    let credential = format!(
+        "https://{}:x-oauth-basic@github.com\n",
+        t!(env::var("TOOLSTATE_REPO_ACCESS_TOKEN")),
+    );
+    let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials");
+    t!(fs::write(&git_credential_path, credential));
+
+    let status = Command::new("git").arg("clone")
+        .arg("--depth=1")
+        .arg(t!(env::var("TOOLSTATE_REPO")))
+        .status();
+    let success = match status {
+        Ok(s) => s.success(),
+        Err(_) => false,
+    };
+    if !success {
+        panic!("git clone successful (status: {:?})", status);
+    }
+
+    let old_toolstate = t!(fs::read("rust-toolstate/_data/latest.json"));
+    let old_toolstate: Vec<RepoState> = t!(serde_json::from_slice(&old_toolstate));
+
+    let message = format!("({} CI update)", OS.expect("linux/windows only"));
+    let mut success = false;
+    for _ in 1..=5 {
+        // Update the toolstate results (the new commit-to-toolstate mapping) in the toolstate repo.
+        change_toolstate(&current_toolstate, &old_toolstate, in_beta_week);
+
+        // `git commit` failing means nothing to commit.
+        let status = t!(Command::new("git")
+            .current_dir("rust-toolstate")
+            .arg("commit")
+            .arg("-a")
+            .arg("-m")
+            .arg(&message)
+            .status());
+        if !status.success() {
+            success = true;
+            break;
+        }
+
+        let status = t!(Command::new("git")
+            .current_dir("rust-toolstate")
+            .arg("push")
+            .arg("origin")
+            .arg("master")
+            .status());
+        // If we successfully push, exit.
+        if status.success() {
+            success = true;
+            break;
+        }
+        eprintln!("Sleeping for 3 seconds before retrying push");
+        std::thread::sleep(std::time::Duration::from_secs(3));
+        let status = t!(Command::new("git")
+            .current_dir("rust-toolstate")
+            .arg("fetch")
+            .arg("origin")
+            .arg("master")
+            .status());
+        assert!(status.success());
+        let status = t!(Command::new("git")
+            .current_dir("rust-toolstate")
+            .arg("reset")
+            .arg("--hard")
+            .arg("origin/master")
+            .status());
+        assert!(status.success());
+    }
+
+    if !success {
+        panic!("Failed to update toolstate repository with new data");
+    }
+}
+
+fn change_toolstate(
+    current_toolstate: &ToolstateData,
+    old_toolstate: &[RepoState],
+    in_beta_week: bool,
+) {
+    let mut regressed = false;
+    for repo_state in old_toolstate {
+        let tool = &repo_state.tool;
+        let state = if cfg!(linux) {
+            &repo_state.linux
+        } else if cfg!(windows) {
+            &repo_state.windows
+        } else {
+            unimplemented!()
+        };
+        let new_state = current_toolstate[tool.as_str()];
+
+        if new_state != *state {
+            eprintln!("The state of `{}` has changed from `{}` to `{}`", tool, state, new_state);
+            if (new_state as u8) < (*state as u8) {
+                if !["rustc-guide", "miri", "embedded-book"].contains(&tool.as_str()) {
+                    regressed = true;
+                }
+            }
+        }
+    }
+
+    if regressed && in_beta_week {
+        std::process::exit(1);
+    }
+
+    let commit = t!(std::process::Command::new("git")
+        .arg("rev-parse")
+        .arg("HEAD")
+        .output());
+    let commit = t!(String::from_utf8(commit.stdout));
+
+    let toolstate_serialized = t!(serde_json::to_string(&current_toolstate));
+
+    let history_path = format!("rust-toolstate/history/{}.tsv", OS.expect("linux/windows only"));
+    let mut file = t!(fs::read_to_string(&history_path));
+    let end_of_first_line = file.find('\n').unwrap();
+    file.insert_str(end_of_first_line, &format!("{}\t{}\n", commit, toolstate_serialized));
+    t!(fs::write(&history_path, file));
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+struct RepoState {
+    tool: String,
+    windows: ToolState,
+    linux: ToolState,
+    commit: String,
+    datetime: String,
+}
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 6f8a630..6824b7a 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -15,6 +15,7 @@
 
 use crate::config::Config;
 use crate::builder::Builder;
+use crate::cache::Interned;
 
 /// Returns the `name` as the filename of a static library for `target`.
 pub fn staticlib(name: &str, target: &str) -> String {
@@ -306,3 +307,15 @@
         false
     }
 }
+
+pub fn use_host_linker(target: &Interned<String>) -> bool {
+    // FIXME: this information should be gotten by checking the linker flavor
+    // of the rustc target
+    !(
+        target.contains("emscripten") ||
+        target.contains("wasm32") ||
+        target.contains("nvptx") ||
+        target.contains("fortanix") ||
+        target.contains("fuchsia")
+    )
+}
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index 70d6bad..5248e41 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -163,7 +163,7 @@
         NO_LLVM_ASSERTIONS: 1
       # MSVC tools tests
       x86_64-msvc-tools:
-        SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows
+        SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py
         RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json
 
       # 32/64-bit MinGW builds.
diff --git a/src/ci/azure-pipelines/master.yml b/src/ci/azure-pipelines/master.yml
index e2baa92..9c5a15a 100644
--- a/src/ci/azure-pipelines/master.yml
+++ b/src/ci/azure-pipelines/master.yml
@@ -16,10 +16,7 @@
 - checkout: self
   fetchDepth: 2
 
-- script: |
-    export MESSAGE_FILE=$(mktemp -t msg.XXXXXX)
-    . src/ci/docker/x86_64-gnu-tools/repo.sh
-    commit_toolstate_change "$MESSAGE_FILE" "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE" "$TOOLSTATE_REPO_ACCESS_TOKEN"
+- script: src/ci/publish_toolstate.sh
   displayName: Publish toolstate
   env:
     TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN)
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index a2d83ec..872f2c3 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -16,6 +16,13 @@
 
 Images will output artifacts in an `obj` dir at the root of a repository.
 
+**NOTE**: Re-using the same `obj` dir with different docker images with
+the same target triple (e.g. `dist-x86_64-linux` and `dist-various-1`)
+may result in strange linker errors, due shared library versions differing between platforms.
+
+If you encounter any issues when using multiple Docker images, try deleting your `obj` directory
+before running your command.
+
 ## Filesystem layout
 
 - Each directory, excluding `scripts` and `disabled`, corresponds to a docker image
diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
index 17aa789..925d5ca 100755
--- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
@@ -12,7 +12,7 @@
 git clone https://github.com/CraneStation/wasi-libc
 
 cd wasi-libc
-git reset --hard a94d2d04e7722b323573da2bd04e909a5763d35b
+git reset --hard f645f498dfbbbc00a7a97874d33082d3605c3f21
 make -j$(nproc) INSTALL_DIR=/wasm32-wasi install
 
 cd ..
diff --git a/src/ci/docker/x86_64-gnu-tools/Dockerfile b/src/ci/docker/x86_64-gnu-tools/Dockerfile
index 7687a6c..5119340 100644
--- a/src/ci/docker/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-tools/Dockerfile
@@ -17,9 +17,7 @@
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY x86_64-gnu-tools/checkregression.py /tmp/
 COPY x86_64-gnu-tools/checktools.sh /tmp/
-COPY x86_64-gnu-tools/repo.sh /tmp/
 
 # Run rustbook with `linkcheck` feature enabled
 ENV CHECK_LINKS 1
@@ -27,4 +25,4 @@
 ENV RUST_CONFIGURE_ARGS \
   --build=x86_64-unknown-linux-gnu \
   --save-toolstates=/tmp/toolstate/toolstates.json
-ENV SCRIPT /tmp/checktools.sh ../x.py /tmp/toolstate/toolstates.json linux
+ENV SCRIPT /tmp/checktools.sh ../x.py
diff --git a/src/ci/docker/x86_64-gnu-tools/checkregression.py b/src/ci/docker/x86_64-gnu-tools/checkregression.py
deleted file mode 100755
index 4fbb8c4..0000000
--- a/src/ci/docker/x86_64-gnu-tools/checkregression.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-## This script has two purposes: detect any tool that *regressed*, which is used
-## during the week before the beta branches to reject PRs; and detect any tool
-## that *changed* to see if we need to update the toolstate repo.
-
-import sys
-import json
-
-# Regressions for these tools during the beta cutoff week do not cause failure.
-# See `status_check` in `checktools.sh` for tools that have to pass on the
-# beta/stable branches.
-REGRESSION_OK = ["rustc-guide", "miri", "embedded-book"]
-
-if __name__ == '__main__':
-    os_name = sys.argv[1]
-    toolstate_file = sys.argv[2]
-    current_state = sys.argv[3]
-    verb = sys.argv[4] # 'regressed' or 'changed'
-
-    with open(toolstate_file, 'r') as f:
-        toolstate = json.load(f)
-    with open(current_state, 'r') as f:
-        current = json.load(f)
-
-    regressed = False
-    for cur in current:
-        tool = cur['tool']
-        state = cur[os_name]
-        new_state = toolstate.get(tool, '')
-        if verb == 'regressed':
-            updated = new_state < state
-        elif verb == 'changed':
-            updated = new_state != state
-        else:
-            print('Unknown verb {}'.format(updated))
-            sys.exit(2)
-        if updated:
-            print(
-                'The state of "{}" has {} from "{}" to "{}"'
-                .format(tool, verb, state, new_state)
-            )
-            if not (verb == 'regressed' and tool in REGRESSION_OK):
-                regressed = True
-
-    if regressed:
-        sys.exit(1)
diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh
index ebb8c0b..e57fe22 100755
--- a/src/ci/docker/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh
@@ -3,18 +3,6 @@
 set -eu
 
 X_PY="$1"
-TOOLSTATE_FILE="$(realpath -m $2)"
-OS="$3"
-COMMIT="$(git rev-parse HEAD)"
-CHANGED_FILES="$(git diff --name-status HEAD HEAD^)"
-SIX_WEEK_CYCLE="$(( ($(date +%s) / 86400 - 20) % 42 ))"
-# ^ Number of days after the last promotion of beta.
-#   Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens.
-#   The Wednesday after this has value 0.
-#   We track this value to prevent regressing tools in the last week of the 6-week cycle.
-
-mkdir -p "$(dirname $TOOLSTATE_FILE)"
-touch "$TOOLSTATE_FILE"
 
 # Try to test all the tools and store the build/test success in the TOOLSTATE_FILE
 
@@ -34,106 +22,4 @@
 
 set -e
 
-cat "$TOOLSTATE_FILE"
-echo
-
-# This function checks if a particular tool is *not* in status "test-pass".
-check_tool_failed() {
-    grep -vq '"'"$1"'":"test-pass"' "$TOOLSTATE_FILE"
-}
-
-# This function checks that if a tool's submodule changed, the tool's state must improve
-verify_submodule_changed() {
-    echo "Verifying status of $1..."
-    if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]$2$"; then
-        echo "This PR updated '$2', verifying if status is 'test-pass'..."
-        if check_tool_failed "$1"; then
-            echo
-            echo "⚠️ We detected that this PR updated '$1', but its tests failed."
-            echo
-            echo "If you do intend to update '$1', please check the error messages above and"
-            echo "commit another update."
-            echo
-            echo "If you do NOT intend to update '$1', please ensure you did not accidentally"
-            echo "change the submodule at '$2'. You may ask your reviewer for the"
-            echo "proper steps."
-            exit 3
-        fi
-    fi
-}
-
-# deduplicates the submodule check and the assertion that on beta some tools MUST be passing.
-# $1 should be "submodule_changed" to only check tools that got changed by this PR,
-# or "beta_required" to check all tools that have $2 set to "beta".
-check_dispatch() {
-    if [ "$1" = submodule_changed ]; then
-        # ignore $2 (branch id)
-        verify_submodule_changed $3 $4
-    elif [ "$2" = beta ]; then
-        echo "Requiring test passing for $3..."
-        if check_tool_failed "$3"; then
-            exit 4
-        fi
-    fi
-}
-
-# List all tools here.
-# This function gets called with "submodule_changed" for each PR that changed a submodule,
-# and with "beta_required" for each PR that lands on beta/stable.
-# The purpose of this function is to *reject* PRs if a tool is not "test-pass" and
-# (a) the tool's submodule has been updated, or (b) we landed on beta/stable and the
-# tool has to "test-pass" on that branch.
-status_check() {
-    check_dispatch $1 beta book src/doc/book
-    check_dispatch $1 beta nomicon src/doc/nomicon
-    check_dispatch $1 beta reference src/doc/reference
-    check_dispatch $1 beta rust-by-example src/doc/rust-by-example
-    check_dispatch $1 beta edition-guide src/doc/edition-guide
-    check_dispatch $1 beta rls src/tools/rls
-    check_dispatch $1 beta rustfmt src/tools/rustfmt
-    check_dispatch $1 beta clippy-driver src/tools/clippy
-    # These tools are not required on the beta/stable branches, but they *do* cause
-    # PRs to fail if a submodule update does not fix them.
-    # They will still cause failure during the beta cutoff week, unless `checkregression.py`
-    # exempts them from that.
-    check_dispatch $1 nightly miri src/tools/miri
-    check_dispatch $1 nightly embedded-book src/doc/embedded-book
-    check_dispatch $1 nightly rustc-guide src/doc/rustc-guide
-}
-
-# If this PR is intended to update one of these tools, do not let the build pass
-# when they do not test-pass.
-
-status_check "submodule_changed"
-
-CHECK_NOT="$(readlink -f "$(dirname $0)/checkregression.py")"
-# This callback is called by `commit_toolstate_change`, see `repo.sh`.
-change_toolstate() {
-    # only update the history
-    if python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" changed; then
-        echo 'Toolstate is not changed. Not updating.'
-    else
-        if [ $SIX_WEEK_CYCLE -ge 35 ]; then
-            # Reject any regressions during the week before beta cutoff.
-            python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed
-        fi
-        sed -i "1 a\\
-$COMMIT\t$(cat "$TOOLSTATE_FILE")
-" "history/$OS.tsv"
-    fi
-}
-
-if [ "$RUST_RELEASE_CHANNEL" = nightly ]; then
-    if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then
-        . "$(dirname $0)/repo.sh"
-        MESSAGE_FILE=$(mktemp -t msg.XXXXXX)
-        echo "($OS CI update)" > "$MESSAGE_FILE"
-        commit_toolstate_change "$MESSAGE_FILE" change_toolstate
-        rm -f "$MESSAGE_FILE"
-    fi
-    exit 0
-fi
-
-# abort compilation if an important tool doesn't build
-# (this code is reachable if not on the nightly channel)
-status_check "beta_required"
+python2.7 "$X_PY" test check-tools
diff --git a/src/ci/docker/x86_64-gnu-tools/repo.sh b/src/ci/docker/x86_64-gnu-tools/repo.sh
deleted file mode 100644
index 82700a0..0000000
--- a/src/ci/docker/x86_64-gnu-tools/repo.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/sh
-
-# This file provides the function `commit_toolstate_change` for pushing a change
-# to the `rust-toolstate` repository.
-#
-# The function relies on a GitHub bot user, which should have a Personal access
-# token defined in the environment variable $TOOLSTATE_REPO_ACCESS_TOKEN. If for
-# some reason you need to change the token, please update the Azure Pipelines
-# variable group.
-#
-#   1. Generate a new Personal access token:
-#
-#       * Login to the bot account, and go to Settings -> Developer settings ->
-#           Personal access tokens
-#       * Click "Generate new token"
-#       * Enable the "public_repo" permission, then click "Generate token"
-#       * Copy the generated token (should be a 40-digit hexadecimal number).
-#           Save it somewhere secure, as the token would be gone once you leave
-#           the page.
-#
-#   2. Update the variable group in Azure Pipelines
-#
-#       * Ping a member of the infrastructure team to do this.
-#
-#   4. Replace the email address below if the bot account identity is changed
-#
-#       * See <https://help.github.com/articles/about-commit-email-addresses/>
-#           if a private email by GitHub is wanted.
-
-commit_toolstate_change() {
-    OLDFLAGS="$-"
-    set -eu
-
-    git config --global user.email '7378925+rust-toolstate-update@users.noreply.github.com'
-    git config --global user.name 'Rust Toolstate Update'
-    git config --global credential.helper store
-    printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \
-        > "$HOME/.git-credentials"
-    git clone --depth=1 $TOOLSTATE_REPO
-
-    cd rust-toolstate
-    FAILURE=1
-    MESSAGE_FILE="$1"
-    shift
-    for RETRY_COUNT in 1 2 3 4 5; do
-        # Call the callback.
-        # - If we are in the `auto` branch (pre-landing), this is called from `checktools.sh` and
-        #   the callback is `change_toolstate` in that file. The purpose of this is to publish the
-        #   test results (the new commit-to-toolstate mapping) in the toolstate repo.
-        # - If we are in the `master` branch (post-landing), this is called by the CI pipeline
-        #   and the callback is `src/tools/publish_toolstate.py`. The purpose is to publish
-        #   the new "current" toolstate in the toolstate repo.
-        "$@"
-        # `git commit` failing means nothing to commit.
-        FAILURE=0
-        git commit -a -F "$MESSAGE_FILE" || break
-        # On failure randomly sleep for 0 to 3 seconds as a crude way to introduce jittering.
-        git push origin master && break || sleep $(LC_ALL=C tr -cd 0-3 < /dev/urandom | head -c 1)
-        FAILURE=1
-        git fetch origin master
-        git reset --hard origin/master
-    done
-    cd ..
-
-    set +eu
-    set "-$OLDFLAGS"
-    return $FAILURE
-}
diff --git a/src/ci/publish_toolstate.sh b/src/ci/publish_toolstate.sh
new file mode 100755
index 0000000..d8ff740
--- /dev/null
+++ b/src/ci/publish_toolstate.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+set -eu
+
+# The following lines are also found in src/bootstrap/toolstate.rs,
+# so if updating here, please also update that file.
+
+export MESSAGE_FILE=$(mktemp -t msg.XXXXXX)
+
+git config --global user.email '7378925+rust-toolstate-update@users.noreply.github.com'
+git config --global user.name 'Rust Toolstate Update'
+git config --global credential.helper store
+printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \
+    > "$HOME/.git-credentials"
+git clone --depth=1 $TOOLSTATE_REPO
+
+cd rust-toolstate
+FAILURE=1
+for RETRY_COUNT in 1 2 3 4 5; do
+    #  The purpose is to publish the new "current" toolstate in the toolstate repo.
+    "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" \
+        "$(git log --format=%s -n1 HEAD)" \
+        "$MESSAGE_FILE" \
+        "$TOOLSTATE_REPO_ACCESS_TOKEN"
+    # `git commit` failing means nothing to commit.
+    FAILURE=0
+    git commit -a -F "$MESSAGE_FILE" || break
+    # On failure randomly sleep for 0 to 3 seconds as a crude way to introduce jittering.
+    git push origin master && break || sleep $(LC_ALL=C tr -cd 0-3 < /dev/urandom | head -c 1)
+    FAILURE=1
+    git fetch origin master
+    git reset --hard origin/master
+done
diff --git a/src/ci/run.sh b/src/ci/run.sh
index ae5b224..38d1d2b 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -23,7 +23,7 @@
 ci_dir=`cd $(dirname $0) && pwd`
 source "$ci_dir/shared.sh"
 
-if [ ! isCI ] || isCiBranch auto || isCiBranch beta; then
+if ! isCI || isCiBranch auto || isCiBranch beta; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
 fi
 
diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide
index 934380b..7c56708 160000
--- a/src/doc/rustc-guide
+++ b/src/doc/rustc-guide
@@ -1 +1 @@
-Subproject commit 934380b7cfceaaa4e1b9bb0de4a372f32725520b
+Subproject commit 7c56708aab7986ca390221e8e8902f7de7f9b076
diff --git a/src/liballoc/alloc/tests.rs b/src/liballoc/alloc/tests.rs
index 956298d..c902971 100644
--- a/src/liballoc/alloc/tests.rs
+++ b/src/liballoc/alloc/tests.rs
@@ -22,7 +22,7 @@
 }
 
 #[bench]
-#[cfg(not(miri))] // Miri does not support benchmarks
+#[cfg_attr(miri, ignore)] // Miri does not support benchmarks
 fn alloc_owned_small(b: &mut Bencher) {
     b.iter(|| {
         let _: Box<_> = box 10;
diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs
index d2bdda8..fc96045 100644
--- a/src/liballoc/borrow.rs
+++ b/src/liballoc/borrow.rs
@@ -195,14 +195,10 @@
     }
 
     fn clone_from(&mut self, source: &Self) {
-        if let Owned(ref mut dest) = *self {
-            if let Owned(ref o) = *source {
-                o.borrow().clone_into(dest);
-                return;
-            }
+        match (self, source) {
+            (&mut Owned(ref mut dest), &Owned(ref o)) => o.borrow().clone_into(dest),
+            (t, s) => *t = s.clone(),
         }
-
-        *self = source.clone();
     }
 }
 
@@ -449,9 +445,7 @@
     fn add_assign(&mut self, rhs: &'a str) {
         if self.is_empty() {
             *self = Cow::Borrowed(rhs)
-        } else if rhs.is_empty() {
-            return;
-        } else {
+        } else if !rhs.is_empty() {
             if let Cow::Borrowed(lhs) = *self {
                 let mut s = String::with_capacity(lhs.len() + rhs.len());
                 s.push_str(lhs);
@@ -467,9 +461,7 @@
     fn add_assign(&mut self, rhs: Cow<'a, str>) {
         if self.is_empty() {
             *self = rhs
-        } else if rhs.is_empty() {
-            return;
-        } else {
+        } else if !rhs.is_empty() {
             if let Cow::Borrowed(lhs) = *self {
                 let mut s = String::with_capacity(lhs.len() + rhs.len());
                 s.push_str(lhs);
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 51ad3a0..1c39a37 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -61,7 +61,60 @@
 //! T` obtained from [`Box::<T>::into_raw`] may be deallocated using the
 //! [`Global`] allocator with [`Layout::for_value(&*value)`].
 //!
+//! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented
+//! as a single pointer and is also ABI-compatible with C pointers
+//! (i.e. the C type `T*`). This means that if you have extern "C"
+//! Rust functions that will be called from C, you can define those
+//! Rust functions using `Box<T>` types, and use `T*` as corresponding
+//! type on the C side. As an example, consider this C header which
+//! declares functions that create and destroy some kind of `Foo`
+//! value:
 //!
+//! ```c
+//! /* C header */
+//!
+//! /* Returns ownership to the caller */
+//! struct Foo* foo_new(void);
+//!
+//! /* Takes ownership from the caller; no-op when invoked with NULL */
+//! void foo_delete(struct Foo*);
+//! ```
+//!
+//! These two functions might be implemented in Rust as follows. Here, the
+//! `struct Foo*` type from C is translated to `Box<Foo>`, which captures
+//! the ownership constraints. Note also that the nullable argument to
+//! `foo_delete` is represented in Rust as `Option<Box<Foo>>`, since `Box<Foo>`
+//! cannot be null.
+//!
+//! ```
+//! #[repr(C)]
+//! pub struct Foo;
+//!
+//! #[no_mangle]
+//! pub extern "C" fn foo_new() -> Box<Foo> {
+//!     Box::new(Foo)
+//! }
+//!
+//! #[no_mangle]
+//! pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}
+//! ```
+//!
+//! Even though `Box<T>` has the same representation and C ABI as a C pointer,
+//! this does not mean that you can convert an arbitrary `T*` into a `Box<T>`
+//! and expect things to work. `Box<T>` values will always be fully aligned,
+//! non-null pointers. Moreover, the destructor for `Box<T>` will attempt to
+//! free the value with the global allocator. In general, the best practice
+//! is to only use `Box<T>` for pointers that originated from the global
+//! allocator.
+//!
+//! **Important.** At least at present, you should avoid using
+//! `Box<T>` types for functions that are defined in C but invoked
+//! from Rust. In those cases, you should directly mirror the C types
+//! as closely as possible. Using types like `Box<T>` where the C
+//! definition is just using `T*` can lead to undefined behavior, as
+//! described in [rust-lang/unsafe-code-guidelines#198][ucg#198].
+//!
+//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
 //! [dereferencing]: ../../std/ops/trait.Deref.html
 //! [`Box`]: struct.Box.html
 //! [`Box<T>`]: struct.Box.html
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index a0c9263..6ee2283 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -808,7 +808,21 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<#[may_dangle] T> Drop for LinkedList<T> {
     fn drop(&mut self) {
-        while let Some(_) = self.pop_front_node() {}
+        struct DropGuard<'a, T>(&'a mut LinkedList<T>);
+
+        impl<'a, T> Drop for DropGuard<'a, T> {
+            fn drop(&mut self) {
+                // Continue the same loop we do below. This only runs when a destructor has
+                // panicked. If another one panics this will abort.
+                while let Some(_) = self.0.pop_front_node() {}
+            }
+        }
+
+        while let Some(node) = self.pop_front_node() {
+            let guard = DropGuard(self);
+            drop(node);
+            mem::forget(guard);
+        }
     }
 }
 
diff --git a/src/liballoc/collections/linked_list/tests.rs b/src/liballoc/collections/linked_list/tests.rs
index 94b92df..1b1d8ea 100644
--- a/src/liballoc/collections/linked_list/tests.rs
+++ b/src/liballoc/collections/linked_list/tests.rs
@@ -182,7 +182,7 @@
 
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
-#[cfg(not(miri))] // Miri does not support threads
+#[cfg_attr(miri, ignore)] // Miri does not support threads
 fn test_send() {
     let n = list_from(&[1, 2, 3]);
     thread::spawn(move || {
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs
index 7795083..9136136 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -144,11 +144,23 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<#[may_dangle] T> Drop for VecDeque<T> {
     fn drop(&mut self) {
+        /// Runs the destructor for all items in the slice when it gets dropped (normally or
+        /// during unwinding).
+        struct Dropper<'a, T>(&'a mut [T]);
+
+        impl<'a, T> Drop for Dropper<'a, T> {
+            fn drop(&mut self) {
+                unsafe {
+                    ptr::drop_in_place(self.0);
+                }
+            }
+        }
+
         let (front, back) = self.as_mut_slices();
         unsafe {
+            let _back_dropper = Dropper(back);
             // use drop for [T]
             ptr::drop_in_place(front);
-            ptr::drop_in_place(back);
         }
         // RawVec handles deallocation
     }
@@ -2809,7 +2821,22 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Extend<A> for VecDeque<A> {
     fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
-        iter.into_iter().for_each(move |elt| self.push_back(elt));
+        // This function should be the moral equivalent of:
+        //
+        //      for item in iter.into_iter() {
+        //          self.push_back(item);
+        //      }
+        let mut iter = iter.into_iter();
+        while let Some(element) = iter.next() {
+            if self.len() == self.capacity() {
+                let (lower, _) = iter.size_hint();
+                self.reserve(lower.saturating_add(1));
+            }
+
+            let head = self.head;
+            self.head = self.wrap_add(self.head, 1);
+            unsafe { self.buffer_write(head, element); }
+        }
     }
 }
 
diff --git a/src/liballoc/collections/vec_deque/tests.rs b/src/liballoc/collections/vec_deque/tests.rs
index 8dc097c..f2ce5b1 100644
--- a/src/liballoc/collections/vec_deque/tests.rs
+++ b/src/liballoc/collections/vec_deque/tests.rs
@@ -3,7 +3,7 @@
 use ::test;
 
 #[bench]
-#[cfg(not(miri))] // Miri does not support benchmarks
+#[cfg_attr(miri, ignore)] // Miri does not support benchmarks
 fn bench_push_back_100(b: &mut test::Bencher) {
     let mut deq = VecDeque::with_capacity(101);
     b.iter(|| {
@@ -16,7 +16,7 @@
 }
 
 #[bench]
-#[cfg(not(miri))] // Miri does not support benchmarks
+#[cfg_attr(miri, ignore)] // Miri does not support benchmarks
 fn bench_push_front_100(b: &mut test::Bencher) {
     let mut deq = VecDeque::with_capacity(101);
     b.iter(|| {
@@ -29,7 +29,7 @@
 }
 
 #[bench]
-#[cfg(not(miri))] // Miri does not support benchmarks
+#[cfg_attr(miri, ignore)] // Miri does not support benchmarks
 fn bench_pop_back_100(b: &mut test::Bencher) {
     let mut deq = VecDeque::<i32>::with_capacity(101);
 
@@ -43,7 +43,7 @@
 }
 
 #[bench]
-#[cfg(not(miri))] // Miri does not support benchmarks
+#[cfg_attr(miri, ignore)] // Miri does not support benchmarks
 fn bench_pop_front_100(b: &mut test::Bencher) {
     let mut deq = VecDeque::<i32>::with_capacity(101);
 
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 2254cde..1ff1c3c 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -1648,10 +1648,8 @@
 
     /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
     ///
-    /// It is up to the caller to ensure that the object is still alive when accessing it through
-    /// the pointer.
-    ///
-    /// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
+    /// The pointer is valid only if there are some strong references. The pointer may be dangling
+    /// or even [`null`] otherwise.
     ///
     /// # Examples
     ///
@@ -1731,14 +1729,18 @@
     /// This can be used to safely get a strong reference (by calling [`upgrade`]
     /// later) or to deallocate the weak count by dropping the `Weak<T>`.
     ///
-    /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
-    /// returned.
+    /// It takes ownership of one weak count (with the exception of pointers created by [`new`],
+    /// as these don't have any corresponding weak count).
     ///
     /// # Safety
     ///
-    /// The pointer must represent one valid weak count. In other words, it must point to `T` which
-    /// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached
-    /// 0. It is allowed for the strong count to be 0.
+    /// The pointer must have originated from the [`into_raw`] (or [`as_raw`], provided there was
+    /// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
+    /// count.
+    ///
+    /// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
+    /// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
+    /// by [`new`]).
     ///
     /// # Examples
     ///
@@ -1763,11 +1765,13 @@
     /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
     /// ```
     ///
-    /// [`null`]: ../../std/ptr/fn.null.html
     /// [`into_raw`]: struct.Weak.html#method.into_raw
     /// [`upgrade`]: struct.Weak.html#method.upgrade
     /// [`Rc`]: struct.Rc.html
     /// [`Weak`]: struct.Weak.html
+    /// [`as_raw`]: struct.Weak.html#method.as_raw
+    /// [`new`]: struct.Weak.html#method.new
+    /// [`forget`]: ../../std/mem/fn.forget.html
     #[unstable(feature = "weak_into_raw", issue = "60728")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
         if ptr.is_null() {
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 7bf2ff1..19b0086 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -1324,10 +1324,8 @@
 
     /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
     ///
-    /// It is up to the caller to ensure that the object is still alive when accessing it through
-    /// the pointer.
-    ///
-    /// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
+    /// The pointer is valid only if there are some strong references. The pointer may be dangling
+    /// or even [`null`] otherwise.
     ///
     /// # Examples
     ///
@@ -1408,14 +1406,18 @@
     /// This can be used to safely get a strong reference (by calling [`upgrade`]
     /// later) or to deallocate the weak count by dropping the `Weak<T>`.
     ///
-    /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
-    /// returned.
+    /// It takes ownership of one weak count (with the exception of pointers created by [`new`],
+    /// as these don't have any corresponding weak count).
     ///
     /// # Safety
     ///
-    /// The pointer must represent one valid weak count. In other words, it must point to `T` which
-    /// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached
-    /// 0. It is allowed for the strong count to be 0.
+    /// The pointer must have originated from the [`into_raw`] (or [`as_raw'], provided there was
+    /// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
+    /// count.
+    ///
+    /// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
+    /// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
+    /// by [`new`]).
     ///
     /// # Examples
     ///
@@ -1440,11 +1442,13 @@
     /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
     /// ```
     ///
-    /// [`null`]: ../../std/ptr/fn.null.html
+    /// [`as_raw`]: struct.Weak.html#method.as_raw
+    /// [`new`]: struct.Weak.html#method.new
     /// [`into_raw`]: struct.Weak.html#method.into_raw
     /// [`upgrade`]: struct.Weak.html#method.upgrade
     /// [`Weak`]: struct.Weak.html
     /// [`Arc`]: struct.Arc.html
+    /// [`forget`]: ../../std/mem/fn.forget.html
     #[unstable(feature = "weak_into_raw", issue = "60728")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
         if ptr.is_null() {
diff --git a/src/liballoc/sync/tests.rs b/src/liballoc/sync/tests.rs
index 9220f5e..9ddba49 100644
--- a/src/liballoc/sync/tests.rs
+++ b/src/liballoc/sync/tests.rs
@@ -29,7 +29,7 @@
 
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
-#[cfg(not(miri))] // Miri does not support threads
+#[cfg_attr(miri, ignore)] // Miri does not support threads
 fn manually_share_arc() {
     let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
     let arc_v = Arc::new(v);
@@ -334,7 +334,7 @@
 
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
-#[cfg(not(miri))] // Miri does not support threads
+#[cfg_attr(miri, ignore)] // Miri does not support threads
 fn test_weak_count_locked() {
     let mut a = Arc::new(atomic::AtomicBool::new(false));
     let a2 = a.clone();
diff --git a/src/liballoc/tests/cow_str.rs b/src/liballoc/tests/cow_str.rs
index 6f357ed..62a5c24 100644
--- a/src/liballoc/tests/cow_str.rs
+++ b/src/liballoc/tests/cow_str.rs
@@ -138,4 +138,7 @@
     let c2: Cow<'_, str> = Cow::Owned(s);
     c1.clone_from(&c2);
     assert!(c1.into_owned().capacity() >= 25);
+    let mut c3: Cow<'_, str> = Cow::Borrowed("bye");
+    c3.clone_from(&c2);
+    assert_eq!(c2, c3);
 }
diff --git a/src/liballoc/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs
index daa49c4..54a77d6 100644
--- a/src/liballoc/tests/linked_list.rs
+++ b/src/liballoc/tests/linked_list.rs
@@ -1,4 +1,5 @@
 use std::collections::LinkedList;
+use std::panic::catch_unwind;
 
 #[test]
 fn test_basic() {
@@ -529,3 +530,109 @@
         assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
     }
 }
+
+
+#[test]
+fn test_drop() {
+    static mut DROPS: i32 = 0;
+    struct Elem;
+    impl Drop for Elem {
+        fn drop(&mut self) {
+            unsafe {
+                DROPS += 1;
+            }
+        }
+    }
+
+    let mut ring = LinkedList::new();
+    ring.push_back(Elem);
+    ring.push_front(Elem);
+    ring.push_back(Elem);
+    ring.push_front(Elem);
+    drop(ring);
+
+    assert_eq!(unsafe { DROPS }, 4);
+}
+
+#[test]
+fn test_drop_with_pop() {
+    static mut DROPS: i32 = 0;
+    struct Elem;
+    impl Drop for Elem {
+        fn drop(&mut self) {
+            unsafe {
+                DROPS += 1;
+            }
+        }
+    }
+
+    let mut ring = LinkedList::new();
+    ring.push_back(Elem);
+    ring.push_front(Elem);
+    ring.push_back(Elem);
+    ring.push_front(Elem);
+
+    drop(ring.pop_back());
+    drop(ring.pop_front());
+    assert_eq!(unsafe { DROPS }, 2);
+
+    drop(ring);
+    assert_eq!(unsafe { DROPS }, 4);
+}
+
+#[test]
+fn test_drop_clear() {
+    static mut DROPS: i32 = 0;
+    struct Elem;
+    impl Drop for Elem {
+        fn drop(&mut self) {
+            unsafe {
+                DROPS += 1;
+            }
+        }
+    }
+
+    let mut ring = LinkedList::new();
+    ring.push_back(Elem);
+    ring.push_front(Elem);
+    ring.push_back(Elem);
+    ring.push_front(Elem);
+    ring.clear();
+    assert_eq!(unsafe { DROPS }, 4);
+
+    drop(ring);
+    assert_eq!(unsafe { DROPS }, 4);
+}
+
+#[test]
+fn test_drop_panic() {
+    static mut DROPS: i32 = 0;
+
+    struct D(bool);
+
+    impl Drop for D {
+        fn drop(&mut self) {
+            unsafe {
+                DROPS += 1;
+            }
+
+            if self.0 {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    let mut q = LinkedList::new();
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_front(D(false));
+    q.push_front(D(false));
+    q.push_front(D(true));
+
+    catch_unwind(move || drop(q)).ok();
+
+    assert_eq!(unsafe { DROPS }, 8);
+}
diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs
index d9707b9..ec45de7 100644
--- a/src/liballoc/tests/slice.rs
+++ b/src/liballoc/tests/slice.rs
@@ -388,7 +388,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_sort() {
     let mut rng = thread_rng();
 
@@ -1610,7 +1610,7 @@
     let moduli = &[5, 20, 50];
 
     #[cfg(miri)]
-    let lens = (1..13);
+    let lens = 1..13;
     #[cfg(miri)]
     let moduli = &[10];
 
diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs
index cb73c7c..1b01124 100644
--- a/src/liballoc/tests/str.rs
+++ b/src/liballoc/tests/str.rs
@@ -166,7 +166,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_unsafe_slice() {
     assert_eq!("ab", unsafe {"abc".get_unchecked(0..2)});
     assert_eq!("bc", unsafe {"abc".get_unchecked(1..3)});
@@ -483,8 +483,8 @@
     }
 
     #[test]
-    #[cfg(not(target_os = "emscripten"))] // hits an OOM
-    #[cfg(not(miri))] // Miri is too slow
+    #[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM
+    #[cfg_attr(miri, ignore)] // Miri is too slow
     fn simple_big() {
         fn a_million_letter_x() -> String {
             let mut i = 0;
@@ -1069,7 +1069,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_chars_decoding() {
     let mut bytes = [0; 4];
     for c in (0..0x110000).filter_map(std::char::from_u32) {
@@ -1081,7 +1081,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_chars_rev_decoding() {
     let mut bytes = [0; 4];
     for c in (0..0x110000).filter_map(std::char::from_u32) {
@@ -1380,7 +1380,6 @@
     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
 }
 
-#[cfg(not(miri))] // Miri is too slow
 fn check_contains_all_substrings(s: &str) {
     assert!(s.contains(""));
     for i in 0..s.len() {
@@ -1391,7 +1390,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn strslice_issue_16589() {
     assert!("bananas".contains("nana"));
 
@@ -1408,7 +1407,7 @@
 
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_strslice_contains() {
     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
     check_contains_all_substrings(x);
diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs
index 55edf56..fe7b4ff 100644
--- a/src/liballoc/tests/string.rs
+++ b/src/liballoc/tests/string.rs
@@ -523,7 +523,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not support signalling OOM
+#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
 fn test_try_reserve() {
 
     // These are the interesting cases:
@@ -601,7 +601,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not support signalling OOM
+#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
 fn test_try_reserve_exact() {
 
     // This is exactly the same as test_try_reserve with the method changed.
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 9ee254f..5e788d6 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -1080,7 +1080,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not support signalling OOM
+#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
 fn test_try_reserve() {
 
     // These are the interesting cases:
@@ -1183,7 +1183,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not support signalling OOM
+#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
 fn test_try_reserve_exact() {
 
     // This is exactly the same as test_try_reserve with the method changed.
diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs
index 5a0162a..1ab3694 100644
--- a/src/liballoc/tests/vec_deque.rs
+++ b/src/liballoc/tests/vec_deque.rs
@@ -2,6 +2,7 @@
 use std::collections::{vec_deque::Drain, VecDeque};
 use std::fmt::Debug;
 use std::mem::size_of;
+use std::panic::catch_unwind;
 use std::{isize, usize};
 
 use crate::hash;
@@ -710,6 +711,39 @@
 }
 
 #[test]
+fn test_drop_panic() {
+    static mut DROPS: i32 = 0;
+
+    struct D(bool);
+
+    impl Drop for D {
+        fn drop(&mut self) {
+            unsafe {
+                DROPS += 1;
+            }
+
+            if self.0 {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    let mut q = VecDeque::new();
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_front(D(false));
+    q.push_front(D(false));
+    q.push_front(D(true));
+
+    catch_unwind(move || drop(q)).ok();
+
+    assert_eq!(unsafe { DROPS }, 8);
+}
+
+#[test]
 fn test_reserve_grow() {
     // test growth path A
     // [T o o H] -> [T o o H . . . . ]
@@ -1100,7 +1134,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not support signalling OOM
+#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
 fn test_try_reserve() {
     // These are the interesting cases:
     // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
@@ -1214,7 +1248,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not support signalling OOM
+#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
 fn test_try_reserve_exact() {
     // This is exactly the same as test_try_reserve with the method changed.
     // See that test for comments.
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 1a700b9..6e165cc 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -92,7 +92,7 @@
 /// vec[0] = 7;
 /// assert_eq!(vec[0], 7);
 ///
-/// vec.extend([1, 2, 3].iter().cloned());
+/// vec.extend([1, 2, 3].iter().copied());
 ///
 /// for x in &vec {
 ///     println!("{}", x);
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 66d27a2..854942d 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -202,53 +202,18 @@
     #[inline]
     pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
         assert!(mem::size_of::<T>() != 0);
-        let mut iter = iter.into_iter();
-        let size_hint = iter.size_hint();
-
-        match size_hint {
-            (min, Some(max)) if min == max => {
-                // We know the exact number of elements the iterator will produce here
-                let len = min;
-
-                if len == 0 {
-                    return &mut [];
-                }
-
-                self.ensure_capacity(len);
-
-                let slice = self.ptr.get();
-
-                unsafe {
-                    let mut ptr = self.ptr.get();
-                    for _ in 0..len {
-                        // Write into uninitialized memory.
-                        ptr::write(ptr, iter.next().unwrap());
-                        // Advance the pointer.
-                        ptr = ptr.offset(1);
-                        // Update the pointer per iteration so if `iter.next()` panics
-                        // we destroy the correct amount
-                        self.ptr.set(ptr);
-                    }
-                    slice::from_raw_parts_mut(slice, len)
-                }
-            }
-            _ => {
-                cold_path(move || -> &mut [T] {
-                    let mut vec: SmallVec<[_; 8]> = iter.collect();
-                    if vec.is_empty() {
-                        return &mut [];
-                    }
-                    // Move the content to the arena by copying it and then forgetting
-                    // the content of the SmallVec
-                    unsafe {
-                        let len = vec.len();
-                        let start_ptr = self.alloc_raw_slice(len);
-                        vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
-                        vec.set_len(0);
-                        slice::from_raw_parts_mut(start_ptr, len)
-                    }
-                })
-            }
+        let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect();
+        if vec.is_empty() {
+            return &mut [];
+        }
+        // Move the content to the arena by copying it and then forgetting
+        // the content of the SmallVec
+        unsafe {
+            let len = vec.len();
+            let start_ptr = self.alloc_raw_slice(len);
+            vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
+            vec.set_len(0);
+            slice::from_raw_parts_mut(start_ptr, len)
         }
     }
 
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index 4798769..5c24e3d 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -53,7 +53,7 @@
 
 impl Layout {
     /// Constructs a `Layout` from a given `size` and `align`,
-    /// or returns `LayoutErr` if either of the following conditions
+    /// or returns `LayoutErr` if any of the following conditions
     /// are not met:
     ///
     /// * `align` must not be zero,
@@ -137,7 +137,7 @@
     #[inline]
     pub fn for_value<T: ?Sized>(t: &T) -> Self {
         let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
-        // See rationale in `new` for why this us using an unsafe variant below
+        // See rationale in `new` for why this is using an unsafe variant below
         debug_assert!(Layout::from_size_align(size, align).is_ok());
         unsafe {
             Layout::from_size_align_unchecked(size, align)
@@ -196,7 +196,7 @@
         //    valid.
         //
         // 2. `len + align - 1` can overflow by at most `align - 1`,
-        //    so the &-mask wth `!(align - 1)` will ensure that in the
+        //    so the &-mask with `!(align - 1)` will ensure that in the
         //    case of overflow, `len_rounded_up` will itself be 0.
         //    Thus the returned padding, when added to `len`, yields 0,
         //    which trivially satisfies the alignment `align`.
@@ -239,8 +239,11 @@
     #[unstable(feature = "alloc_layout_extra", issue = "55724")]
     #[inline]
     pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
-        let padded_size = self.size().checked_add(self.padding_needed_for(self.align()))
-            .ok_or(LayoutErr { private: () })?;
+        // This cannot overflow. Quoting from the invariant of Layout:
+        // > `size`, when rounded up to the nearest multiple of `align`,
+        // > must not overflow (i.e., the rounded value must be less than
+        // > `usize::MAX`)
+        let padded_size = self.size() + self.padding_needed_for(self.align());
         let alloc_size = padded_size.checked_mul(n)
             .ok_or(LayoutErr { private: () })?;
 
@@ -253,7 +256,7 @@
 
     /// Creates a layout describing the record for `self` followed by
     /// `next`, including any necessary padding to ensure that `next`
-    /// will be properly aligned. Note that the result layout will
+    /// will be properly aligned. Note that the resulting layout will
     /// satisfy the alignment properties of both `self` and `next`.
     ///
     /// The resulting layout will be the same as that of a C struct containing
@@ -310,8 +313,7 @@
     pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutErr> {
         let new_size = self.size().checked_add(next.size())
             .ok_or(LayoutErr { private: () })?;
-        let layout = Layout::from_size_align(new_size, self.align())?;
-        Ok(layout)
+        Layout::from_size_align(new_size, self.align())
     }
 
     /// Creates a layout describing the record for a `[T; n]`.
@@ -388,7 +390,7 @@
 }
 
 /// A memory allocator that can be registered as the standard library’s default
-/// though the `#[global_allocator]` attributes.
+/// through the `#[global_allocator]` attribute.
 ///
 /// Some of the methods require that a memory block be *currently
 /// allocated* via an allocator. This means that:
@@ -459,7 +461,7 @@
     /// # Errors
     ///
     /// Returning a null pointer indicates that either memory is exhausted
-    /// or `layout` does not meet allocator's size or alignment constraints.
+    /// or `layout` does not meet this allocator's size or alignment constraints.
     ///
     /// Implementations are encouraged to return null on memory
     /// exhaustion rather than aborting, but this is not
@@ -1046,7 +1048,7 @@
     /// Captures a common usage pattern for allocators.
     ///
     /// The returned block is suitable for passing to the
-    /// `alloc`/`realloc` methods of this allocator.
+    /// `realloc`/`dealloc` methods of this allocator.
     ///
     /// Note to implementors: If this returns `Ok(ptr)`, then `ptr`
     /// must be considered "currently allocated" and must be
@@ -1112,7 +1114,7 @@
     /// Captures a common usage pattern for allocators.
     ///
     /// The returned block is suitable for passing to the
-    /// `alloc`/`realloc` methods of this allocator.
+    /// `realloc`/`dealloc` methods of this allocator.
     ///
     /// Note to implementors: If this returns `Ok(ptr)`, then `ptr`
     /// must be considered "currently allocated" and must be
@@ -1143,9 +1145,9 @@
         where Self: Sized
     {
         match Layout::array::<T>(n) {
-            Ok(ref layout) if layout.size() > 0 => {
+            Ok(layout) if layout.size() > 0 => {
                 unsafe {
-                    self.alloc(layout.clone()).map(|p| p.cast())
+                    self.alloc(layout).map(|p| p.cast())
                 }
             }
             _ => Err(AllocErr),
@@ -1159,7 +1161,7 @@
     /// Captures a common usage pattern for allocators.
     ///
     /// The returned block is suitable for passing to the
-    /// `alloc`/`realloc` methods of this allocator.
+    /// `realloc`/`dealloc` methods of this allocator.
     ///
     /// # Safety
     ///
@@ -1193,9 +1195,9 @@
         where Self: Sized
     {
         match (Layout::array::<T>(n_old), Layout::array::<T>(n_new)) {
-            (Ok(ref k_old), Ok(ref k_new)) if k_old.size() > 0 && k_new.size() > 0 => {
+            (Ok(k_old), Ok(k_new)) if k_old.size() > 0 && k_new.size() > 0 => {
                 debug_assert!(k_old.align() == k_new.align());
-                self.realloc(ptr.cast(), k_old.clone(), k_new.size()).map(NonNull::cast)
+                self.realloc(ptr.cast(), k_old, k_new.size()).map(NonNull::cast)
             }
             _ => {
                 Err(AllocErr)
@@ -1227,8 +1229,8 @@
         where Self: Sized
     {
         match Layout::array::<T>(n) {
-            Ok(ref k) if k.size() > 0 => {
-                Ok(self.dealloc(ptr.cast(), k.clone()))
+            Ok(k) if k.size() > 0 => {
+                Ok(self.dealloc(ptr.cast(), k))
             }
             _ => {
                 Err(AllocErr)
diff --git a/src/libcore/benches/any.rs b/src/libcore/benches/any.rs
index ceb507a..53099b7 100644
--- a/src/libcore/benches/any.rs
+++ b/src/libcore/benches/any.rs
@@ -1,5 +1,5 @@
 use core::any::*;
-use test::{Bencher, black_box};
+use test::{black_box, Bencher};
 
 #[bench]
 fn bench_downcast_ref(b: &mut Bencher) {
diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs
index e921dd1..76ccd3d 100644
--- a/src/libcore/benches/ascii.rs
+++ b/src/libcore/benches/ascii.rs
@@ -22,17 +22,9 @@
 //
 // Therefore:
 fn branchless_to_ascii_upper_case(byte: u8) -> u8 {
-    byte &
-    !(
-        (
-            byte.wrapping_add(0x1f) &
-            !byte.wrapping_add(0x05) &
-            0x80
-        ) >> 2
-    )
+    byte & !((byte.wrapping_add(0x1f) & !byte.wrapping_add(0x05) & 0x80) >> 2)
 }
 
-
 macro_rules! benches {
     ($( fn $name: ident($arg: ident: &mut [u8]) $body: block )+ @iter $( $is_: ident, )+) => {
         benches! {@
@@ -254,12 +246,15 @@
 }
 
 macro_rules! repeat {
-    ($s: expr) => { concat!($s, $s, $s, $s, $s, $s, $s, $s, $s, $s) }
+    ($s: expr) => {
+        concat!($s, $s, $s, $s, $s, $s, $s, $s, $s, $s)
+    };
 }
 
 const SHORT: &'static str = "Alice's";
 const MEDIUM: &'static str = "Alice's Adventures in Wonderland";
-const LONG: &'static str = repeat!(r#"
+const LONG: &'static str = repeat!(
+    r#"
     La Guida di Bragia, a Ballad Opera for the Marionette Theatre (around 1850)
     Alice's Adventures in Wonderland (1865)
     Phantasmagoria and Other Poems (1869)
@@ -275,8 +270,10 @@
     What the Tortoise Said to Achilles (1895)
     Three Sunsets and Other Poems (1898)
     The Manlet (1903)[106]
-"#);
+"#
+);
 
+#[rustfmt::skip]
 const ASCII_UPPERCASE_MAP: [u8; 256] = [
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
@@ -330,6 +327,7 @@
 }
 use self::AsciiCharacterClass::*;
 
+#[rustfmt::skip]
 static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 256] = [
 //  _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f
     C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_
diff --git a/src/libcore/benches/char/methods.rs b/src/libcore/benches/char/methods.rs
index af934c1..a9a08a4 100644
--- a/src/libcore/benches/char/methods.rs
+++ b/src/libcore/benches/char/methods.rs
@@ -25,8 +25,13 @@
 
 #[bench]
 fn bench_to_digit_radix_var(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle()
-        .zip(RADIX.iter().cycle())
-        .take(10_000)
-        .map(|(c, radix)| c.to_digit(*radix)).min())
+    b.iter(|| {
+        CHARS
+            .iter()
+            .cycle()
+            .zip(RADIX.iter().cycle())
+            .take(10_000)
+            .map(|(c, radix)| c.to_digit(*radix))
+            .min()
+    })
 }
diff --git a/src/libcore/benches/fmt.rs b/src/libcore/benches/fmt.rs
index 92f10c7..dd72a33 100644
--- a/src/libcore/benches/fmt.rs
+++ b/src/libcore/benches/fmt.rs
@@ -1,5 +1,5 @@
-use std::io::{self, Write as IoWrite};
 use std::fmt::{self, Write as FmtWrite};
+use std::io::{self, Write as IoWrite};
 use test::Bencher;
 
 #[bench]
diff --git a/src/libcore/benches/hash/sip.rs b/src/libcore/benches/hash/sip.rs
index 5baba42..725c864 100644
--- a/src/libcore/benches/hash/sip.rs
+++ b/src/libcore/benches/hash/sip.rs
@@ -1,7 +1,7 @@
 #![allow(deprecated)]
 
 use core::hash::*;
-use test::{Bencher, black_box};
+use test::{black_box, Bencher};
 
 fn hash_bytes<H: Hasher>(mut s: H, x: &[u8]) -> u64 {
     Hasher::write(&mut s, x);
@@ -44,11 +44,11 @@
 #[bench]
 fn bench_long_str(b: &mut Bencher) {
     let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
-incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
-exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
-irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
-pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
-officia deserunt mollit anim id est laborum.";
+             incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
+             exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
+             irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
+             pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
+             officia deserunt mollit anim id est laborum.";
     b.iter(|| {
         assert_eq!(hash(&s), 17717065544121360093);
     })
@@ -58,9 +58,7 @@
 fn bench_u32(b: &mut Bencher) {
     let u = 162629500u32;
     let u = black_box(u);
-    b.iter(|| {
-        hash(&u)
-    });
+    b.iter(|| hash(&u));
     b.bytes = 8;
 }
 
@@ -70,9 +68,7 @@
     let u = black_box(u);
     let k1 = black_box(0x1);
     let k2 = black_box(0x2);
-    b.iter(|| {
-        hash_with(SipHasher::new_with_keys(k1, k2), &u)
-    });
+    b.iter(|| hash_with(SipHasher::new_with_keys(k1, k2), &u));
     b.bytes = 8;
 }
 
@@ -80,62 +76,48 @@
 fn bench_u64(b: &mut Bencher) {
     let u = 16262950014981195938u64;
     let u = black_box(u);
-    b.iter(|| {
-        hash(&u)
-    });
+    b.iter(|| hash(&u));
     b.bytes = 8;
 }
 
 #[bench]
 fn bench_bytes_4(b: &mut Bencher) {
     let data = black_box([b' '; 4]);
-    b.iter(|| {
-        hash_bytes(SipHasher::default(), &data)
-    });
+    b.iter(|| hash_bytes(SipHasher::default(), &data));
     b.bytes = 4;
 }
 
 #[bench]
 fn bench_bytes_7(b: &mut Bencher) {
     let data = black_box([b' '; 7]);
-    b.iter(|| {
-        hash_bytes(SipHasher::default(), &data)
-    });
+    b.iter(|| hash_bytes(SipHasher::default(), &data));
     b.bytes = 7;
 }
 
 #[bench]
 fn bench_bytes_8(b: &mut Bencher) {
     let data = black_box([b' '; 8]);
-    b.iter(|| {
-        hash_bytes(SipHasher::default(), &data)
-    });
+    b.iter(|| hash_bytes(SipHasher::default(), &data));
     b.bytes = 8;
 }
 
 #[bench]
 fn bench_bytes_a_16(b: &mut Bencher) {
     let data = black_box([b' '; 16]);
-    b.iter(|| {
-        hash_bytes(SipHasher::default(), &data)
-    });
+    b.iter(|| hash_bytes(SipHasher::default(), &data));
     b.bytes = 16;
 }
 
 #[bench]
 fn bench_bytes_b_32(b: &mut Bencher) {
     let data = black_box([b' '; 32]);
-    b.iter(|| {
-        hash_bytes(SipHasher::default(), &data)
-    });
+    b.iter(|| hash_bytes(SipHasher::default(), &data));
     b.bytes = 32;
 }
 
 #[bench]
 fn bench_bytes_c_128(b: &mut Bencher) {
     let data = black_box([b' '; 128]);
-    b.iter(|| {
-        hash_bytes(SipHasher::default(), &data)
-    });
+    b.iter(|| hash_bytes(SipHasher::default(), &data));
     b.bytes = 128;
 }
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index 7dcfad8..fb6b4b7 100644
--- a/src/libcore/benches/iter.rs
+++ b/src/libcore/benches/iter.rs
@@ -1,5 +1,5 @@
 use core::iter::*;
-use test::{Bencher, black_box};
+use test::{black_box, Bencher};
 
 #[bench]
 fn bench_rposition(b: &mut Bencher) {
@@ -14,7 +14,11 @@
     b.iter(|| {
         let it = 0..100;
         let mut sum = 0;
-        it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true);
+        it.skip_while(|&x| {
+            sum += x;
+            sum < 4000
+        })
+        .all(|_| true);
     });
 }
 
@@ -29,7 +33,9 @@
     });
 }
 
-fn scatter(x: i32) -> i32 { (x * 31) % 127 }
+fn scatter(x: i32) -> i32 {
+    (x * 31) % 127
+}
 
 #[bench]
 fn bench_max_by_key(b: &mut Bencher) {
@@ -76,23 +82,21 @@
 fn bench_zip_copy(b: &mut Bencher) {
     let source = vec![0u8; 16 * 1024];
     let mut dst = black_box(vec![0u8; 16 * 1024]);
-    b.iter(|| {
-        copy_zip(&source, &mut dst)
-    })
+    b.iter(|| copy_zip(&source, &mut dst))
 }
 
 #[bench]
 fn bench_zip_add(b: &mut Bencher) {
     let source = vec![1.; 16 * 1024];
     let mut dst = vec![0.; 16 * 1024];
-    b.iter(|| {
-        add_zip(&source, &mut dst)
-    });
+    b.iter(|| add_zip(&source, &mut dst));
 }
 
 /// `Iterator::for_each` implemented as a plain loop.
-fn for_each_loop<I, F>(iter: I, mut f: F) where
-    I: Iterator, F: FnMut(I::Item)
+fn for_each_loop<I, F>(iter: I, mut f: F)
+where
+    I: Iterator,
+    F: FnMut(I::Item),
 {
     for item in iter {
         f(item);
@@ -101,8 +105,10 @@
 
 /// `Iterator::for_each` implemented with `fold` for internal iteration.
 /// (except when `by_ref()` effectively disables that optimization.)
-fn for_each_fold<I, F>(iter: I, mut f: F) where
-    I: Iterator, F: FnMut(I::Item)
+fn for_each_fold<I, F>(iter: I, mut f: F)
+where
+    I: Iterator,
+    F: FnMut(I::Item),
 {
     iter.fold((), move |(), item| f(item));
 }
@@ -137,25 +143,20 @@
     });
 }
 
-
 /// Helper to benchmark `sum` for iterators taken by value which
 /// can optimize `fold`, and by reference which cannot.
 macro_rules! bench_sums {
     ($bench_sum:ident, $bench_ref_sum:ident, $iter:expr) => {
         #[bench]
         fn $bench_sum(b: &mut Bencher) {
-            b.iter(|| -> i64 {
-                $iter.map(black_box).sum()
-            });
+            b.iter(|| -> i64 { $iter.map(black_box).sum() });
         }
 
         #[bench]
         fn $bench_ref_sum(b: &mut Bencher) {
-            b.iter(|| -> i64 {
-                $iter.map(black_box).by_ref().sum()
-            });
+            b.iter(|| -> i64 { $iter.map(black_box).by_ref().sum() });
         }
-    }
+    };
 }
 
 bench_sums! {
@@ -286,7 +287,10 @@
     let t: Vec<_> = (0..100_000).collect();
 
     b.iter(|| {
-        let s = v.iter().zip(t.iter()).skip(10000)
+        let s = v
+            .iter()
+            .zip(t.iter())
+            .skip(10000)
             .take_while(|t| *t.0 < 10100)
             .map(|(a, b)| *a + *b)
             .sum::<u64>();
@@ -299,7 +303,10 @@
     let t: Vec<_> = (0..100_000).collect();
 
     b.iter(|| {
-        let s = v.iter().skip(10000).zip(t.iter().skip(10000))
+        let s = v
+            .iter()
+            .skip(10000)
+            .zip(t.iter().skip(10000))
             .take_while(|t| *t.0 < 10100)
             .map(|(a, b)| *a + *b)
             .sum::<u64>();
@@ -309,23 +316,17 @@
 
 #[bench]
 fn bench_filter_count(b: &mut Bencher) {
-    b.iter(|| {
-        (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()
-    })
+    b.iter(|| (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count())
 }
 
 #[bench]
 fn bench_filter_ref_count(b: &mut Bencher) {
-    b.iter(|| {
-        (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
-    })
+    b.iter(|| (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count())
 }
 
 #[bench]
 fn bench_filter_chain_count(b: &mut Bencher) {
-    b.iter(|| {
-        (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()
-    })
+    b.iter(|| (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count())
 }
 
 #[bench]
diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs
index dea2963d..6932c7f 100644
--- a/src/libcore/benches/lib.rs
+++ b/src/libcore/benches/lib.rs
@@ -6,9 +6,9 @@
 mod any;
 mod ascii;
 mod char;
+mod fmt;
 mod hash;
 mod iter;
 mod num;
 mod ops;
 mod slice;
-mod fmt;
diff --git a/src/libcore/benches/num/flt2dec/mod.rs b/src/libcore/benches/num/flt2dec/mod.rs
index 4153745..b810dd1 100644
--- a/src/libcore/benches/num/flt2dec/mod.rs
+++ b/src/libcore/benches/num/flt2dec/mod.rs
@@ -3,17 +3,17 @@
     mod grisu;
 }
 
+use core::num::flt2dec::MAX_SIG_DIGITS;
+use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
 use std::f64;
 use std::io::Write;
 use std::vec::Vec;
 use test::Bencher;
-use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
-use core::num::flt2dec::MAX_SIG_DIGITS;
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
         FullDecoded::Finite(decoded) => decoded,
-        full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
+        full_decoded => panic!("expected finite, got {:?} instead", full_decoded),
     }
 }
 
diff --git a/src/libcore/benches/num/flt2dec/strategy/dragon.rs b/src/libcore/benches/num/flt2dec/strategy/dragon.rs
index 60660b1..4052fec 100644
--- a/src/libcore/benches/num/flt2dec/strategy/dragon.rs
+++ b/src/libcore/benches/num/flt2dec/strategy/dragon.rs
@@ -1,6 +1,6 @@
-use std::{i16, f64};
 use super::super::*;
 use core::num::flt2dec::strategy::dragon::*;
+use std::{f64, i16};
 use test::Bencher;
 
 #[bench]
diff --git a/src/libcore/benches/num/flt2dec/strategy/grisu.rs b/src/libcore/benches/num/flt2dec/strategy/grisu.rs
index 841feba..4950747 100644
--- a/src/libcore/benches/num/flt2dec/strategy/grisu.rs
+++ b/src/libcore/benches/num/flt2dec/strategy/grisu.rs
@@ -1,12 +1,12 @@
-use std::{i16, f64};
 use super::super::*;
 use core::num::flt2dec::strategy::grisu::*;
+use std::{f64, i16};
 use test::Bencher;
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
         FullDecoded::Finite(decoded) => decoded,
-        full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
+        full_decoded => panic!("expected finite, got {:?} instead", full_decoded),
     }
 }
 
diff --git a/src/libcore/benches/num/mod.rs b/src/libcore/benches/num/mod.rs
index 2dcdf2b..852d4e4 100644
--- a/src/libcore/benches/num/mod.rs
+++ b/src/libcore/benches/num/mod.rs
@@ -1,8 +1,8 @@
-mod flt2dec;
 mod dec2flt;
+mod flt2dec;
 
-use test::Bencher;
 use std::str::FromStr;
+use test::Bencher;
 
 const ASCII_NUMBERS: [&str; 19] = [
     "0",
@@ -27,7 +27,7 @@
 ];
 
 macro_rules! from_str_bench {
-    ($mac:ident, $t:ty) => (
+    ($mac:ident, $t:ty) => {
         #[bench]
         fn $mac(b: &mut Bencher) {
             b.iter(|| {
@@ -39,11 +39,11 @@
                     .max()
             })
         }
-    )
+    };
 }
 
 macro_rules! from_str_radix_bench {
-    ($mac:ident, $t:ty, $radix:expr) => (
+    ($mac:ident, $t:ty, $radix:expr) => {
         #[bench]
         fn $mac(b: &mut Bencher) {
             b.iter(|| {
@@ -55,7 +55,7 @@
                     .max()
             })
         }
-    )
+    };
 }
 
 from_str_bench!(bench_u8_from_str, u8);
diff --git a/src/libcore/benches/ops.rs b/src/libcore/benches/ops.rs
index 80649f3..0a2be8a2 100644
--- a/src/libcore/benches/ops.rs
+++ b/src/libcore/benches/ops.rs
@@ -4,17 +4,16 @@
 // Overhead of dtors
 
 struct HasDtor {
-    _x: isize
+    _x: isize,
 }
 
 impl Drop for HasDtor {
-    fn drop(&mut self) {
-    }
+    fn drop(&mut self) {}
 }
 
 #[bench]
 fn alloc_obj_with_dtor(b: &mut Bencher) {
     b.iter(|| {
-        HasDtor { _x : 10 };
+        HasDtor { _x: 10 };
     })
 }
diff --git a/src/libcore/benches/slice.rs b/src/libcore/benches/slice.rs
index 711a8df..06b37cb 100644
--- a/src/libcore/benches/slice.rs
+++ b/src/libcore/benches/slice.rs
@@ -8,11 +8,12 @@
 }
 
 fn binary_search<F>(b: &mut Bencher, cache: Cache, mapper: F)
-    where F: Fn(usize) -> usize
+where
+    F: Fn(usize) -> usize,
 {
     let size = match cache {
-        Cache::L1 => 1000, // 8kb
-        Cache::L2 => 10_000, // 80kb
+        Cache::L1 => 1000,      // 8kb
+        Cache::L2 => 10_000,    // 80kb
         Cache::L3 => 1_000_000, // 8Mb
     };
     let v = (0..size).map(&mapper).collect::<Vec<_>>();
diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs
index 617bdd2..6e0865e 100644
--- a/src/libcore/bool.rs
+++ b/src/libcore/bool.rs
@@ -9,17 +9,13 @@
     /// ```
     /// #![feature(bool_to_option)]
     ///
-    /// assert_eq!(false.then(0), None);
-    /// assert_eq!(true.then(0), Some(0));
+    /// assert_eq!(false.then_some(0), None);
+    /// assert_eq!(true.then_some(0), Some(0));
     /// ```
     #[unstable(feature = "bool_to_option", issue = "64260")]
     #[inline]
-    pub fn then<T>(self, t: T) -> Option<T> {
-        if self {
-            Some(t)
-        } else {
-            None
-        }
+    pub fn then_some<T>(self, t: T) -> Option<T> {
+        if self { Some(t) } else { None }
     }
 
     /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise.
@@ -29,16 +25,12 @@
     /// ```
     /// #![feature(bool_to_option)]
     ///
-    /// assert_eq!(false.then_with(|| 0), None);
-    /// assert_eq!(true.then_with(|| 0), Some(0));
+    /// assert_eq!(false.then(|| 0), None);
+    /// assert_eq!(true.then(|| 0), Some(0));
     /// ```
     #[unstable(feature = "bool_to_option", issue = "64260")]
     #[inline]
-    pub fn then_with<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
-        if self {
-            Some(f())
-        } else {
-            None
-        }
+    pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
+        if self { Some(f()) } else { None }
     }
 }
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index 1ec614e..5c63eeb 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -553,8 +553,7 @@
     pub fn is_alphabetic(self) -> bool {
         match self {
             'a'..='z' | 'A'..='Z' => true,
-            c if c > '\x7f' => derived_property::Alphabetic(c),
-            _ => false,
+            c => c > '\x7f' && derived_property::Alphabetic(c),
         }
     }
 
@@ -585,8 +584,7 @@
     pub fn is_lowercase(self) -> bool {
         match self {
             'a'..='z' => true,
-            c if c > '\x7f' => derived_property::Lowercase(c),
-            _ => false,
+            c => c > '\x7f' && derived_property::Lowercase(c),
         }
     }
 
@@ -617,8 +615,7 @@
     pub fn is_uppercase(self) -> bool {
         match self {
             'A'..='Z' => true,
-            c if c > '\x7f' => derived_property::Uppercase(c),
-            _ => false,
+            c => c > '\x7f' && derived_property::Uppercase(c),
         }
     }
 
@@ -646,8 +643,7 @@
     pub fn is_whitespace(self) -> bool {
         match self {
             ' ' | '\x09'..='\x0d' => true,
-            c if c > '\x7f' => property::White_Space(c),
-            _ => false,
+            c => c > '\x7f' && property::White_Space(c),
         }
     }
 
@@ -744,8 +740,7 @@
     pub fn is_numeric(self) -> bool {
         match self {
             '0'..='9' => true,
-            c if c > '\x7f' => general_category::N(c),
-            _ => false,
+            c => c > '\x7f' && general_category::N(c),
         }
     }
 
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index a5f355c..fd4be02 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -1005,6 +1005,7 @@
 
 // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
 mod impls {
+    use crate::hint::unreachable_unchecked;
     use crate::cmp::Ordering::{self, Less, Greater, Equal};
 
     macro_rules! partial_eq_impl {
@@ -1125,7 +1126,16 @@
     impl Ord for bool {
         #[inline]
         fn cmp(&self, other: &bool) -> Ordering {
-            (*self as u8).cmp(&(*other as u8))
+            // Casting to i8's and converting the difference to an Ordering generates
+            // more optimal assembly.
+            // See <https://github.com/rust-lang/rust/issues/66780> for more info.
+            match (*self as i8) - (*other as i8) {
+                -1 => Less,
+                0 => Equal,
+                1 => Greater,
+                // SAFETY: bool as i8 returns 0 or 1, so the difference can't be anything else
+                _ => unsafe { unreachable_unchecked() },
+            }
         }
     }
 
diff --git a/src/libcore/convert.rs b/src/libcore/convert/mod.rs
similarity index 98%
rename from src/libcore/convert.rs
rename to src/libcore/convert/mod.rs
index 08802b3..b7db3e4 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert/mod.rs
@@ -40,6 +40,11 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+mod num;
+
+#[unstable(feature = "convert_float_to_int", issue = "67057")]
+pub use num::FloatToInt;
+
 /// The identity function.
 ///
 /// Two things are important to note about this function:
@@ -286,7 +291,7 @@
 /// [`Into`].
 ///
 /// One should always prefer implementing `From` over [`Into`]
-/// because implementing `From` automatically provides one with a implementation of [`Into`]
+/// because implementing `From` automatically provides one with an implementation of [`Into`]
 /// thanks to the blanket implementation in the standard library.
 ///
 /// Only implement [`Into`] if a conversion to a type outside the current crate is required.
@@ -562,6 +567,7 @@
 ///
 /// [#64715]: https://github.com/rust-lang/rust/issues/64715
 #[stable(feature = "convert_infallible", since = "1.34.0")]
+#[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead.
 #[rustc_reservation_impl = "permitting this impl would forbid us from adding \
                             `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
 impl<T> From<!> for T {
diff --git a/src/libcore/convert/num.rs b/src/libcore/convert/num.rs
new file mode 100644
index 0000000..6f5ee75
--- /dev/null
+++ b/src/libcore/convert/num.rs
@@ -0,0 +1,449 @@
+use super::{From, TryFrom};
+use crate::num::TryFromIntError;
+
+mod private {
+    /// This trait being unreachable from outside the crate
+    /// prevents other implementations of the `FloatToInt` trait,
+    /// which allows potentially adding more trait methods after the trait is `#[stable]`.
+    #[unstable(feature = "convert_float_to_int", issue = "67057")]
+    pub trait Sealed {}
+}
+
+/// Supporting trait for inherent methods of `f32` and `f64` such as `round_unchecked_to`.
+/// Typically doesn’t need to be used directly.
+#[unstable(feature = "convert_float_to_int", issue = "67057")]
+pub trait FloatToInt<Int>: private::Sealed + Sized {
+    #[cfg(not(bootstrap))]
+    #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+    #[doc(hidden)]
+    unsafe fn approx_unchecked(self) -> Int;
+}
+
+macro_rules! impl_float_to_int {
+    ( $Float: ident => $( $Int: ident )+ ) => {
+        #[unstable(feature = "convert_float_to_int", issue = "67057")]
+        impl private::Sealed for $Float {}
+        $(
+            #[unstable(feature = "convert_float_to_int", issue = "67057")]
+            impl FloatToInt<$Int> for $Float {
+                #[cfg(not(bootstrap))]
+                #[doc(hidden)]
+                #[inline]
+                unsafe fn approx_unchecked(self) -> $Int {
+                    crate::intrinsics::float_to_int_approx_unchecked(self)
+                }
+            }
+        )+
+    }
+}
+
+impl_float_to_int!(f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
+impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
+
+// Conversion traits for primitive integer and float types
+// Conversions T -> T are covered by a blanket impl and therefore excluded
+// Some conversions from and to usize/isize are not implemented due to portability concerns
+macro_rules! impl_from {
+    ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
+        #[$attr]
+        #[doc = $doc]
+        impl From<$Small> for $Large {
+            #[inline]
+            fn from(small: $Small) -> $Large {
+                small as $Large
+            }
+        }
+    };
+    ($Small: ty, $Large: ty, #[$attr:meta]) => {
+        impl_from!($Small,
+                   $Large,
+                   #[$attr],
+                   concat!("Converts `",
+                           stringify!($Small),
+                           "` to `",
+                           stringify!($Large),
+                           "` losslessly."));
+    }
+}
+
+macro_rules! impl_from_bool {
+    ($target: ty, #[$attr:meta]) => {
+        impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
+            stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
+values.
+
+# Examples
+
+```
+assert_eq!(", stringify!($target), "::from(true), 1);
+assert_eq!(", stringify!($target), "::from(false), 0);
+```"));
+    };
+}
+
+// Bool -> Any
+impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
+
+// Unsigned -> Unsigned
+impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// Signed -> Signed
+impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// Unsigned -> Signed
+impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
+// which imply that pointer-sized integers must be at least 16 bits:
+// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
+impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+
+// RISC-V defines the possibility of a 128-bit address space (RV128).
+
+// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
+// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
+// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
+
+// Note: integers can only be represented with full precision in a float if
+// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
+// Lossy float conversions are not implemented at this time.
+
+// Signed -> Float
+impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// Unsigned -> Float
+impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// Float -> Float
+impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// no possible bounds violation
+macro_rules! try_from_unbounded {
+    ($source:ty, $($target:ty),*) => {$(
+        #[stable(feature = "try_from", since = "1.34.0")]
+        impl TryFrom<$source> for $target {
+            type Error = TryFromIntError;
+
+            /// Try to create the target number type from a source
+            /// number type. This returns an error if the source value
+            /// is outside of the range of the target type.
+            #[inline]
+            fn try_from(value: $source) -> Result<Self, Self::Error> {
+                Ok(value as $target)
+            }
+        }
+    )*}
+}
+
+// only negative bounds
+macro_rules! try_from_lower_bounded {
+    ($source:ty, $($target:ty),*) => {$(
+        #[stable(feature = "try_from", since = "1.34.0")]
+        impl TryFrom<$source> for $target {
+            type Error = TryFromIntError;
+
+            /// Try to create the target number type from a source
+            /// number type. This returns an error if the source value
+            /// is outside of the range of the target type.
+            #[inline]
+            fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+                if u >= 0 {
+                    Ok(u as $target)
+                } else {
+                    Err(TryFromIntError(()))
+                }
+            }
+        }
+    )*}
+}
+
+// unsigned to signed (only positive bound)
+macro_rules! try_from_upper_bounded {
+    ($source:ty, $($target:ty),*) => {$(
+        #[stable(feature = "try_from", since = "1.34.0")]
+        impl TryFrom<$source> for $target {
+            type Error = TryFromIntError;
+
+            /// Try to create the target number type from a source
+            /// number type. This returns an error if the source value
+            /// is outside of the range of the target type.
+            #[inline]
+            fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+                if u > (<$target>::max_value() as $source) {
+                    Err(TryFromIntError(()))
+                } else {
+                    Ok(u as $target)
+                }
+            }
+        }
+    )*}
+}
+
+// all other cases
+macro_rules! try_from_both_bounded {
+    ($source:ty, $($target:ty),*) => {$(
+        #[stable(feature = "try_from", since = "1.34.0")]
+        impl TryFrom<$source> for $target {
+            type Error = TryFromIntError;
+
+            /// Try to create the target number type from a source
+            /// number type. This returns an error if the source value
+            /// is outside of the range of the target type.
+            #[inline]
+            fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+                let min = <$target>::min_value() as $source;
+                let max = <$target>::max_value() as $source;
+                if u < min || u > max {
+                    Err(TryFromIntError(()))
+                } else {
+                    Ok(u as $target)
+                }
+            }
+        }
+    )*}
+}
+
+macro_rules! rev {
+    ($mac:ident, $source:ty, $($target:ty),*) => {$(
+        $mac!($target, $source);
+    )*}
+}
+
+// intra-sign conversions
+try_from_upper_bounded!(u16, u8);
+try_from_upper_bounded!(u32, u16, u8);
+try_from_upper_bounded!(u64, u32, u16, u8);
+try_from_upper_bounded!(u128, u64, u32, u16, u8);
+
+try_from_both_bounded!(i16, i8);
+try_from_both_bounded!(i32, i16, i8);
+try_from_both_bounded!(i64, i32, i16, i8);
+try_from_both_bounded!(i128, i64, i32, i16, i8);
+
+// unsigned-to-signed
+try_from_upper_bounded!(u8, i8);
+try_from_upper_bounded!(u16, i8, i16);
+try_from_upper_bounded!(u32, i8, i16, i32);
+try_from_upper_bounded!(u64, i8, i16, i32, i64);
+try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
+
+// signed-to-unsigned
+try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
+try_from_lower_bounded!(i16, u16, u32, u64, u128);
+try_from_lower_bounded!(i32, u32, u64, u128);
+try_from_lower_bounded!(i64, u64, u128);
+try_from_lower_bounded!(i128, u128);
+try_from_both_bounded!(i16, u8);
+try_from_both_bounded!(i32, u16, u8);
+try_from_both_bounded!(i64, u32, u16, u8);
+try_from_both_bounded!(i128, u64, u32, u16, u8);
+
+// usize/isize
+try_from_upper_bounded!(usize, isize);
+try_from_lower_bounded!(isize, usize);
+
+#[cfg(target_pointer_width = "16")]
+mod ptr_try_from_impls {
+    use super::TryFromIntError;
+    use crate::convert::TryFrom;
+
+    try_from_upper_bounded!(usize, u8);
+    try_from_unbounded!(usize, u16, u32, u64, u128);
+    try_from_upper_bounded!(usize, i8, i16);
+    try_from_unbounded!(usize, i32, i64, i128);
+
+    try_from_both_bounded!(isize, u8);
+    try_from_lower_bounded!(isize, u16, u32, u64, u128);
+    try_from_both_bounded!(isize, i8);
+    try_from_unbounded!(isize, i16, i32, i64, i128);
+
+    rev!(try_from_upper_bounded, usize, u32, u64, u128);
+    rev!(try_from_lower_bounded, usize, i8, i16);
+    rev!(try_from_both_bounded, usize, i32, i64, i128);
+
+    rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
+    rev!(try_from_both_bounded, isize, i32, i64, i128);
+}
+
+#[cfg(target_pointer_width = "32")]
+mod ptr_try_from_impls {
+    use super::TryFromIntError;
+    use crate::convert::TryFrom;
+
+    try_from_upper_bounded!(usize, u8, u16);
+    try_from_unbounded!(usize, u32, u64, u128);
+    try_from_upper_bounded!(usize, i8, i16, i32);
+    try_from_unbounded!(usize, i64, i128);
+
+    try_from_both_bounded!(isize, u8, u16);
+    try_from_lower_bounded!(isize, u32, u64, u128);
+    try_from_both_bounded!(isize, i8, i16);
+    try_from_unbounded!(isize, i32, i64, i128);
+
+    rev!(try_from_unbounded, usize, u32);
+    rev!(try_from_upper_bounded, usize, u64, u128);
+    rev!(try_from_lower_bounded, usize, i8, i16, i32);
+    rev!(try_from_both_bounded, usize, i64, i128);
+
+    rev!(try_from_unbounded, isize, u16);
+    rev!(try_from_upper_bounded, isize, u32, u64, u128);
+    rev!(try_from_unbounded, isize, i32);
+    rev!(try_from_both_bounded, isize, i64, i128);
+}
+
+#[cfg(target_pointer_width = "64")]
+mod ptr_try_from_impls {
+    use super::TryFromIntError;
+    use crate::convert::TryFrom;
+
+    try_from_upper_bounded!(usize, u8, u16, u32);
+    try_from_unbounded!(usize, u64, u128);
+    try_from_upper_bounded!(usize, i8, i16, i32, i64);
+    try_from_unbounded!(usize, i128);
+
+    try_from_both_bounded!(isize, u8, u16, u32);
+    try_from_lower_bounded!(isize, u64, u128);
+    try_from_both_bounded!(isize, i8, i16, i32);
+    try_from_unbounded!(isize, i64, i128);
+
+    rev!(try_from_unbounded, usize, u32, u64);
+    rev!(try_from_upper_bounded, usize, u128);
+    rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
+    rev!(try_from_both_bounded, usize, i128);
+
+    rev!(try_from_unbounded, isize, u16, u32);
+    rev!(try_from_upper_bounded, isize, u64, u128);
+    rev!(try_from_unbounded, isize, i32, i64);
+    rev!(try_from_both_bounded, isize, i128);
+}
+
+// Conversion traits for non-zero integer types
+use crate::num::NonZeroI128;
+use crate::num::NonZeroI16;
+use crate::num::NonZeroI32;
+use crate::num::NonZeroI64;
+use crate::num::NonZeroI8;
+use crate::num::NonZeroIsize;
+use crate::num::NonZeroU128;
+use crate::num::NonZeroU16;
+use crate::num::NonZeroU32;
+use crate::num::NonZeroU64;
+use crate::num::NonZeroU8;
+use crate::num::NonZeroUsize;
+
+macro_rules! nzint_impl_from {
+    ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
+        #[$attr]
+        #[doc = $doc]
+        impl From<$Small> for $Large {
+            #[inline]
+            fn from(small: $Small) -> $Large {
+                // SAFETY: input type guarantees the value is non-zero
+                unsafe {
+                    <$Large>::new_unchecked(small.get().into())
+                }
+            }
+        }
+    };
+    ($Small: ty, $Large: ty, #[$attr:meta]) => {
+        nzint_impl_from!($Small,
+                   $Large,
+                   #[$attr],
+                   concat!("Converts `",
+                           stringify!($Small),
+                           "` to `",
+                           stringify!($Large),
+                           "` losslessly."));
+    }
+}
+
+// Non-zero Unsigned -> Non-zero Unsigned
+nzint_impl_from! { NonZeroU8, NonZeroU16, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU8, NonZeroU32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU8, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU8, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU8, NonZeroUsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU16, NonZeroU32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU16, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU16, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU16, NonZeroUsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU32, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU32, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU64, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+
+// Non-zero Signed -> Non-zero Signed
+nzint_impl_from! { NonZeroI8, NonZeroI16, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI8, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI8, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI8, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI8, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI16, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI16, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI16, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI16, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI32, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI32, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroI64, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+
+// NonZero UnSigned -> Non-zero Signed
+nzint_impl_from! { NonZeroU8, NonZeroI16, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU8, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU8, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU8, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU8, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU16, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU16, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU16, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU32, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU32, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
+nzint_impl_from! { NonZeroU64, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 4c941e2..e2f49ee 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -662,7 +662,7 @@
 ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 ///         let val = self.0;
 ///
-///         write!(f, "{:o}", val) // delegate to i32's implementation
+///         fmt::Octal::fmt(&val, f) // delegate to i32's implementation
 ///     }
 /// }
 ///
@@ -712,7 +712,7 @@
 ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 ///         let val = self.0;
 ///
-///         write!(f, "{:b}", val) // delegate to i32's implementation
+///         fmt::Binary::fmt(&val, f) // delegate to i32's implementation
 ///     }
 /// }
 ///
@@ -771,7 +771,7 @@
 ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 ///         let val = self.0;
 ///
-///         write!(f, "{:x}", val) // delegate to i32's implementation
+///         fmt::LowerHex::fmt(&val, f) // delegate to i32's implementation
 ///     }
 /// }
 ///
@@ -824,7 +824,7 @@
 ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 ///         let val = self.0;
 ///
-///         write!(f, "{:X}", val) // delegate to i32's implementation
+///         fmt::UpperHex::fmt(&val, f) // delegate to i32's implementation
 ///     }
 /// }
 ///
@@ -869,7 +869,8 @@
 ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 ///         // use `as` to convert to a `*const T`, which implements Pointer, which we can use
 ///
-///         write!(f, "{:p}", self as *const Length)
+///         let ptr = self as *const Self;
+///         fmt::Pointer::fmt(&ptr, f)
 ///     }
 /// }
 ///
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index a295e65..f4fb9ab 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -64,31 +64,27 @@
 #[inline]
 #[unstable(feature = "renamed_spin_loop", issue = "55002")]
 pub fn spin_loop() {
-    #[cfg(
-        all(
-            any(target_arch = "x86", target_arch = "x86_64"),
-            target_feature = "sse2"
-        )
-    )] {
-        #[cfg(target_arch = "x86")] {
+    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
+    {
+        #[cfg(target_arch = "x86")]
+        {
             unsafe { crate::arch::x86::_mm_pause() };
         }
 
-        #[cfg(target_arch = "x86_64")] {
+        #[cfg(target_arch = "x86_64")]
+        {
             unsafe { crate::arch::x86_64::_mm_pause() };
         }
     }
 
-    #[cfg(
-        any(
-            target_arch = "aarch64",
-            all(target_arch = "arm", target_feature = "v6")
-        )
-    )] {
-        #[cfg(target_arch = "aarch64")] {
+    #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
+    {
+        #[cfg(target_arch = "aarch64")]
+        {
             unsafe { crate::arch::aarch64::__yield() };
         }
-        #[cfg(target_arch = "arm")] {
+        #[cfg(target_arch = "arm")]
+        {
             unsafe { crate::arch::arm::__yield() };
         }
     }
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 19928f3..18aae59 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1144,6 +1144,11 @@
     /// May assume inputs are finite.
     pub fn frem_fast<T>(a: T, b: T) -> T;
 
+    /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
+    /// https://github.com/rust-lang/rust/issues/10184
+    #[cfg(not(bootstrap))]
+    pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
+
 
     /// Returns the number of bits set in an integer type `T`
     pub fn ctpop<T>(x: T) -> T;
diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs
index bbdb169..f21ab8d 100644
--- a/src/libcore/iter/traits/collect.rs
+++ b/src/libcore/iter/traits/collect.rs
@@ -91,9 +91,9 @@
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
-    message="a collection of type `{Self}` cannot be built from an iterator \
-             over elements of type `{A}`",
-    label="a collection of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`",
+    message = "a value of type `{Self}` cannot be built from an iterator \
+               over elements of type `{A}`",
+    label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
 )]
 pub trait FromIterator<A>: Sized {
     /// Creates a value from an iterator.
@@ -116,7 +116,7 @@
     /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> Self;
+    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
 }
 
 /// Conversion into an `Iterator`.
@@ -214,7 +214,7 @@
 
     /// Which kind of iterator are we turning this into?
     #[stable(feature = "rust1", since = "1.0.0")]
-    type IntoIter: Iterator<Item=Self::Item>;
+    type IntoIter: Iterator<Item = Self::Item>;
 
     /// Creates an iterator from a value.
     ///
@@ -340,7 +340,7 @@
     /// assert_eq!("abcdef", &message);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T);
+    fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T);
 }
 
 #[stable(feature = "extend_for_unit", since = "1.28.0")]
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index ec19392..8a514f1 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -74,6 +74,8 @@
 #![feature(const_fn)]
 #![feature(const_fn_union)]
 #![feature(const_generics)]
+#![cfg_attr(not(bootstrap), feature(const_ptr_offset_from))]
+#![cfg_attr(not(bootstrap), feature(const_type_name))]
 #![feature(custom_inner_attributes)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
@@ -100,6 +102,7 @@
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stmt_expr_attributes)]
+#![cfg_attr(not(bootstrap), feature(track_caller))]
 #![feature(transparent_unions)]
 #![feature(unboxed_closures)]
 #![feature(unsized_locals)]
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 86ee673..288017b 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -29,6 +29,7 @@
 /// [arc]: ../../std/sync/struct.Arc.html
 /// [ub]: ../../reference/behavior-considered-undefined.html
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "send_trait")]
 #[rustc_on_unimplemented(
     message="`{Self}` cannot be sent between threads safely",
     label="`{Self}` cannot be sent between threads safely"
@@ -440,6 +441,7 @@
 /// [ub]: ../../reference/behavior-considered-undefined.html
 /// [transmute]: ../../std/mem/fn.transmute.html
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "sync_trait")]
 #[lang = "sync"]
 #[rustc_on_unimplemented(
     message="`{Self}` cannot be shared between threads safely",
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index bba4414..ec926aa 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -510,7 +510,9 @@
 /// **This function is deprecated.** Use [`MaybeUninit<T>`] instead.
 ///
 /// The reason for deprecation is that the function basically cannot be used
-/// correctly: [the Rust compiler assumes][inv] that values are properly initialized.
+/// correctly: it has the same effect as [`MaybeUninit::uninit().assume_init()`][uninit].
+/// As the [`assume_init` documentation][assume_init] explains,
+/// [the Rust compiler assumes][inv] that values are properly initialized.
 /// As a consequence, calling e.g. `mem::uninitialized::<bool>()` causes immediate
 /// undefined behavior for returning a `bool` that is not definitely either `true`
 /// or `false`. Worse, truly uninitialized memory like what gets returned here
@@ -521,6 +523,8 @@
 /// until they are, it is advisable to avoid them.)
 ///
 /// [`MaybeUninit<T>`]: union.MaybeUninit.html
+/// [uninit]: union.MaybeUninit.html#method.uninit
+/// [assume_init]: union.MaybeUninit.html#method.assume_init
 /// [inv]: union.MaybeUninit.html#initialization-invariant
 #[inline]
 #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 913c0f9..ac06f95 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -7,9 +7,10 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[cfg(not(bootstrap))]
+use crate::convert::FloatToInt;
 #[cfg(not(test))]
 use crate::intrinsics;
-
 use crate::mem;
 use crate::num::FpCategory;
 
@@ -400,6 +401,35 @@
         intrinsics::minnumf32(self, other)
     }
 
+    /// Rounds toward zero and converts to any primitive integer type,
+    /// assuming that the value is finite and fits in that type.
+    ///
+    /// ```
+    /// #![feature(float_approx_unchecked_to)]
+    ///
+    /// let value = 4.6_f32;
+    /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+    /// assert_eq!(rounded, 4);
+    ///
+    /// let value = -128.9_f32;
+    /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
+    /// assert_eq!(rounded, std::i8::MIN);
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The value must:
+    ///
+    /// * Not be `NaN`
+    /// * Not be infinite
+    /// * Be representable in the return type `Int`, after truncating off its fractional part
+    #[cfg(not(bootstrap))]
+    #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+    #[inline]
+    pub unsafe fn approx_unchecked_to<Int>(self) -> Int where Self: FloatToInt<Int> {
+        FloatToInt::<Int>::approx_unchecked(self)
+    }
+
     /// Raw transmutation to `u32`.
     ///
     /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 6ca830b..5446ce3 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -7,9 +7,10 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[cfg(not(bootstrap))]
+use crate::convert::FloatToInt;
 #[cfg(not(test))]
 use crate::intrinsics;
-
 use crate::mem;
 use crate::num::FpCategory;
 
@@ -413,6 +414,38 @@
         intrinsics::minnumf64(self, other)
     }
 
+    /// Rounds toward zero and converts to any primitive integer type,
+    /// assuming that the value is finite and fits in that type.
+    ///
+    /// ```
+    /// #![feature(float_approx_unchecked_to)]
+    ///
+    /// let value = 4.6_f32;
+    /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+    /// assert_eq!(rounded, 4);
+    ///
+    /// let value = -128.9_f32;
+    /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
+    /// assert_eq!(rounded, std::i8::MIN);
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// The value must:
+    ///
+    /// * Not be `NaN`
+    /// * Not be infinite
+    /// * Be representable in the return type `Int`, after truncating off its fractional part
+    #[cfg(not(bootstrap))]
+    #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+    #[inline]
+    pub unsafe fn approx_unchecked_to<Int>(self) -> Int
+    where
+        Self: FloatToInt<Int>,
+    {
+        FloatToInt::<Int>::approx_unchecked(self)
+    }
+
     /// Raw transmutation to `u64`.
     ///
     /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 4313248..d1f518d 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -4,7 +4,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::convert::TryFrom;
 use crate::fmt;
 use crate::intrinsics;
 use crate::mem;
@@ -132,7 +131,7 @@
 }
 
 from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
-                             NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
+NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
 
 /// Provides intentionally-wrapped arithmetic on `T`.
 ///
@@ -163,8 +162,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
 #[repr(transparent)]
-pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")]
-                       pub T);
+pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for Wrapping<T> {
@@ -209,30 +207,33 @@
 }
 
 // All these modules are technically private and only exposed for coretests:
-pub mod flt2dec;
-pub mod dec2flt;
 pub mod bignum;
+pub mod dec2flt;
 pub mod diy_float;
+pub mod flt2dec;
 
 mod wrapping;
 
 macro_rules! usize_isize_to_xe_bytes_doc {
-    () => {"
+    () => {
+        "
 
 **Note**: This function returns an array of length 2, 4 or 8 bytes
 depending on the target pointer size.
 
-"}
+"
+    };
 }
 
-
 macro_rules! usize_isize_from_xe_bytes_doc {
-    () => {"
+    () => {
+        "
 
 **Note**: This function takes an array of length 2, 4 or 8 bytes
 depending on the target pointer size.
 
-"}
+"
+    };
 }
 
 macro_rules! int_impl {
@@ -2239,67 +2240,67 @@
 #[lang = "i8"]
 impl i8 {
     int_impl! { i8, i8, u8, 8, -128, 127, "", "", 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
-        "[0x12]", "[0x12]", "", "" }
+    "[0x12]", "[0x12]", "", "" }
 }
 
 #[lang = "i16"]
 impl i16 {
     int_impl! { i16, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
-        "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
+    "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
 }
 
 #[lang = "i32"]
 impl i32 {
     int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",
-        "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
-        "[0x12, 0x34, 0x56, 0x78]", "", "" }
+    "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
+    "[0x12, 0x34, 0x56, 0x78]", "", "" }
 }
 
 #[lang = "i64"]
 impl i64 {
     int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", 12,
-         "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
-         "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-         "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
+    "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
+    "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+    "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
 }
 
 #[lang = "i128"]
 impl i128 {
     int_impl! { i128, i128, u128, 128, -170141183460469231731687303715884105728,
-        170141183460469231731687303715884105727, "", "", 16,
-        "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
-        "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
-        "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
-          0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-        "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
-          0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "" }
+    170141183460469231731687303715884105727, "", "", 16,
+    "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
+    "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
+    "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
+      0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+    "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
+      0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "" }
 }
 
 #[cfg(target_pointer_width = "16")]
 #[lang = "isize"]
 impl isize {
     int_impl! { isize, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234",
-        "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
-        usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
+    usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
 
 #[cfg(target_pointer_width = "32")]
 #[lang = "isize"]
 impl isize {
     int_impl! { isize, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",
-        "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
-        "[0x12, 0x34, 0x56, 0x78]",
-        usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
+    "[0x12, 0x34, 0x56, 0x78]",
+    usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
 
 #[cfg(target_pointer_width = "64")]
 #[lang = "isize"]
 impl isize {
     int_impl! { isize, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "",
-        12, "0xaa00000000006e1", "0x6e10aa",  "0x1234567890123456", "0x5634129078563412",
-         "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-         "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
-         usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    12, "0xaa00000000006e1", "0x6e10aa",  "0x1234567890123456", "0x5634129078563412",
+     "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
 
 macro_rules! uint_impl {
@@ -4061,8 +4062,7 @@
 #[lang = "u8"]
 impl u8 {
     uint_impl! { u8, u8, 8, 255, "", "", 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
-        "[0x12]", "", "" }
-
+    "[0x12]", "", "" }
 
     /// Checks if the value is within the ASCII range.
     ///
@@ -4228,7 +4228,7 @@
     pub fn is_ascii_alphabetic(&self) -> bool {
         match *self {
             b'A'..=b'Z' | b'a'..=b'z' => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -4263,7 +4263,7 @@
     pub fn is_ascii_uppercase(&self) -> bool {
         match *self {
             b'A'..=b'Z' => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -4298,7 +4298,7 @@
     pub fn is_ascii_lowercase(&self) -> bool {
         match *self {
             b'a'..=b'z' => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -4336,7 +4336,7 @@
     pub fn is_ascii_alphanumeric(&self) -> bool {
         match *self {
             b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -4371,7 +4371,7 @@
     pub fn is_ascii_digit(&self) -> bool {
         match *self {
             b'0'..=b'9' => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -4409,7 +4409,7 @@
     pub fn is_ascii_hexdigit(&self) -> bool {
         match *self {
             b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f' => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -4448,7 +4448,7 @@
     pub fn is_ascii_punctuation(&self) -> bool {
         match *self {
             b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~' => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -4483,7 +4483,7 @@
     pub fn is_ascii_graphic(&self) -> bool {
         match *self {
             b'!'..=b'~' => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -4535,7 +4535,7 @@
     pub fn is_ascii_whitespace(&self) -> bool {
         match *self {
             b'\t' | b'\n' | b'\x0C' | b'\r' | b' ' => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -4572,7 +4572,7 @@
     pub fn is_ascii_control(&self) -> bool {
         match *self {
             b'\0'..=b'\x1F' | b'\x7F' => true,
-            _ => false
+            _ => false,
         }
     }
 }
@@ -4580,59 +4580,59 @@
 #[lang = "u16"]
 impl u16 {
     uint_impl! { u16, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
-        "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
+    "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
 }
 
 #[lang = "u32"]
 impl u32 {
     uint_impl! { u32, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678",
-        "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
+    "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
 }
 
 #[lang = "u64"]
 impl u64 {
     uint_impl! { u64, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa",
-        "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
-        "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-        "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
-        "", ""}
+    "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
+    "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+    "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+    "", ""}
 }
 
 #[lang = "u128"]
 impl u128 {
     uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, "", "", 16,
-        "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
-        "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
-        "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
-          0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-        "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
-          0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]",
-         "", ""}
+    "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
+    "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
+    "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
+      0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+    "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
+      0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]",
+     "", ""}
 }
 
 #[cfg(target_pointer_width = "16")]
 #[lang = "usize"]
 impl usize {
     uint_impl! { usize, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
-        "[0x34, 0x12]", "[0x12, 0x34]",
-        usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    "[0x34, 0x12]", "[0x12, 0x34]",
+    usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
 #[cfg(target_pointer_width = "32")]
 #[lang = "usize"]
 impl usize {
     uint_impl! { usize, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678",
-        "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
-        usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
+    usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
 
 #[cfg(target_pointer_width = "64")]
 #[lang = "usize"]
 impl usize {
     uint_impl! { usize, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa",
-        "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
-        "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
-         "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
-        usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+    "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
+    "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+     "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+    usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
 
 /// A classification of floating point numbers.
@@ -4701,13 +4701,15 @@
 /// The error type returned when a checked integral type conversion fails.
 #[stable(feature = "try_from", since = "1.34.0")]
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub struct TryFromIntError(());
+pub struct TryFromIntError(pub(crate) ());
 
 impl TryFromIntError {
-    #[unstable(feature = "int_error_internals",
-               reason = "available through Error trait and this method should \
-                         not be exposed publicly",
-               issue = "0")]
+    #[unstable(
+        feature = "int_error_internals",
+        reason = "available through Error trait and this method should \
+                  not be exposed publicly",
+        issue = "0"
+    )]
     #[doc(hidden)]
     pub fn __description(&self) -> &str {
         "out of range integral type conversion attempted"
@@ -4728,206 +4730,6 @@
     }
 }
 
-// no possible bounds violation
-macro_rules! try_from_unbounded {
-    ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.34.0")]
-        impl TryFrom<$source> for $target {
-            type Error = TryFromIntError;
-
-            /// Try to create the target number type from a source
-            /// number type. This returns an error if the source value
-            /// is outside of the range of the target type.
-            #[inline]
-            fn try_from(value: $source) -> Result<Self, Self::Error> {
-                Ok(value as $target)
-            }
-        }
-    )*}
-}
-
-// only negative bounds
-macro_rules! try_from_lower_bounded {
-    ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.34.0")]
-        impl TryFrom<$source> for $target {
-            type Error = TryFromIntError;
-
-            /// Try to create the target number type from a source
-            /// number type. This returns an error if the source value
-            /// is outside of the range of the target type.
-            #[inline]
-            fn try_from(u: $source) -> Result<$target, TryFromIntError> {
-                if u >= 0 {
-                    Ok(u as $target)
-                } else {
-                    Err(TryFromIntError(()))
-                }
-            }
-        }
-    )*}
-}
-
-// unsigned to signed (only positive bound)
-macro_rules! try_from_upper_bounded {
-    ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.34.0")]
-        impl TryFrom<$source> for $target {
-            type Error = TryFromIntError;
-
-            /// Try to create the target number type from a source
-            /// number type. This returns an error if the source value
-            /// is outside of the range of the target type.
-            #[inline]
-            fn try_from(u: $source) -> Result<$target, TryFromIntError> {
-                if u > (<$target>::max_value() as $source) {
-                    Err(TryFromIntError(()))
-                } else {
-                    Ok(u as $target)
-                }
-            }
-        }
-    )*}
-}
-
-// all other cases
-macro_rules! try_from_both_bounded {
-    ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.34.0")]
-        impl TryFrom<$source> for $target {
-            type Error = TryFromIntError;
-
-            /// Try to create the target number type from a source
-            /// number type. This returns an error if the source value
-            /// is outside of the range of the target type.
-            #[inline]
-            fn try_from(u: $source) -> Result<$target, TryFromIntError> {
-                let min = <$target>::min_value() as $source;
-                let max = <$target>::max_value() as $source;
-                if u < min || u > max {
-                    Err(TryFromIntError(()))
-                } else {
-                    Ok(u as $target)
-                }
-            }
-        }
-    )*}
-}
-
-macro_rules! rev {
-    ($mac:ident, $source:ty, $($target:ty),*) => {$(
-        $mac!($target, $source);
-    )*}
-}
-
-// intra-sign conversions
-try_from_upper_bounded!(u16, u8);
-try_from_upper_bounded!(u32, u16, u8);
-try_from_upper_bounded!(u64, u32, u16, u8);
-try_from_upper_bounded!(u128, u64, u32, u16, u8);
-
-try_from_both_bounded!(i16, i8);
-try_from_both_bounded!(i32, i16, i8);
-try_from_both_bounded!(i64, i32, i16, i8);
-try_from_both_bounded!(i128, i64, i32, i16, i8);
-
-// unsigned-to-signed
-try_from_upper_bounded!(u8, i8);
-try_from_upper_bounded!(u16, i8, i16);
-try_from_upper_bounded!(u32, i8, i16, i32);
-try_from_upper_bounded!(u64, i8, i16, i32, i64);
-try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
-
-// signed-to-unsigned
-try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
-try_from_lower_bounded!(i16, u16, u32, u64, u128);
-try_from_lower_bounded!(i32, u32, u64, u128);
-try_from_lower_bounded!(i64, u64, u128);
-try_from_lower_bounded!(i128, u128);
-try_from_both_bounded!(i16, u8);
-try_from_both_bounded!(i32, u16, u8);
-try_from_both_bounded!(i64, u32, u16, u8);
-try_from_both_bounded!(i128, u64, u32, u16, u8);
-
-// usize/isize
-try_from_upper_bounded!(usize, isize);
-try_from_lower_bounded!(isize, usize);
-
-#[cfg(target_pointer_width = "16")]
-mod ptr_try_from_impls {
-    use super::TryFromIntError;
-    use crate::convert::TryFrom;
-
-    try_from_upper_bounded!(usize, u8);
-    try_from_unbounded!(usize, u16, u32, u64, u128);
-    try_from_upper_bounded!(usize, i8, i16);
-    try_from_unbounded!(usize, i32, i64, i128);
-
-    try_from_both_bounded!(isize, u8);
-    try_from_lower_bounded!(isize, u16, u32, u64, u128);
-    try_from_both_bounded!(isize, i8);
-    try_from_unbounded!(isize, i16, i32, i64, i128);
-
-    rev!(try_from_upper_bounded, usize, u32, u64, u128);
-    rev!(try_from_lower_bounded, usize, i8, i16);
-    rev!(try_from_both_bounded, usize, i32, i64, i128);
-
-    rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
-    rev!(try_from_both_bounded, isize, i32, i64, i128);
-}
-
-#[cfg(target_pointer_width = "32")]
-mod ptr_try_from_impls {
-    use super::TryFromIntError;
-    use crate::convert::TryFrom;
-
-    try_from_upper_bounded!(usize, u8, u16);
-    try_from_unbounded!(usize, u32, u64, u128);
-    try_from_upper_bounded!(usize, i8, i16, i32);
-    try_from_unbounded!(usize, i64, i128);
-
-    try_from_both_bounded!(isize, u8, u16);
-    try_from_lower_bounded!(isize, u32, u64, u128);
-    try_from_both_bounded!(isize, i8, i16);
-    try_from_unbounded!(isize, i32, i64, i128);
-
-    rev!(try_from_unbounded, usize, u32);
-    rev!(try_from_upper_bounded, usize, u64, u128);
-    rev!(try_from_lower_bounded, usize, i8, i16, i32);
-    rev!(try_from_both_bounded, usize, i64, i128);
-
-    rev!(try_from_unbounded, isize, u16);
-    rev!(try_from_upper_bounded, isize, u32, u64, u128);
-    rev!(try_from_unbounded, isize, i32);
-    rev!(try_from_both_bounded, isize, i64, i128);
-}
-
-#[cfg(target_pointer_width = "64")]
-mod ptr_try_from_impls {
-    use super::TryFromIntError;
-    use crate::convert::TryFrom;
-
-    try_from_upper_bounded!(usize, u8, u16, u32);
-    try_from_unbounded!(usize, u64, u128);
-    try_from_upper_bounded!(usize, i8, i16, i32, i64);
-    try_from_unbounded!(usize, i128);
-
-    try_from_both_bounded!(isize, u8, u16, u32);
-    try_from_lower_bounded!(isize, u64, u128);
-    try_from_both_bounded!(isize, i8, i16, i32);
-    try_from_unbounded!(isize, i64, i128);
-
-    rev!(try_from_unbounded, usize, u32, u64);
-    rev!(try_from_upper_bounded, usize, u128);
-    rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
-    rev!(try_from_both_bounded, usize, i128);
-
-    rev!(try_from_unbounded, isize, u16, u32);
-    rev!(try_from_upper_bounded, isize, u64, u128);
-    rev!(try_from_unbounded, isize, i32, i64);
-    rev!(try_from_both_bounded, isize, i128);
-}
-
 #[doc(hidden)]
 trait FromStrRadixHelper: PartialOrd + Copy {
     fn min_value() -> Self;
@@ -4966,9 +4768,11 @@
     use self::IntErrorKind::*;
     use self::ParseIntError as PIE;
 
-    assert!(radix >= 2 && radix <= 36,
-           "from_str_radix_int: must lie in the range `[2, 36]` - found {}",
-           radix);
+    assert!(
+        radix >= 2 && radix <= 36,
+        "from_str_radix_int: must lie in the range `[2, 36]` - found {}",
+        radix
+    );
 
     if src.is_empty() {
         return Err(PIE { kind: Empty });
@@ -5049,10 +4853,12 @@
 }
 
 /// Enum to store the various types of errors that can cause parsing an integer to fail.
-#[unstable(feature = "int_error_matching",
-           reason = "it can be useful to match errors when making error messages \
-                     for integer parsing",
-           issue = "22639")]
+#[unstable(
+    feature = "int_error_matching",
+    reason = "it can be useful to match errors when making error messages \
+              for integer parsing",
+    issue = "22639"
+)]
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[non_exhaustive]
 pub enum IntErrorKind {
@@ -5078,17 +4884,21 @@
 
 impl ParseIntError {
     /// Outputs the detailed cause of parsing an integer failing.
-    #[unstable(feature = "int_error_matching",
-               reason = "it can be useful to match errors when making error messages \
-                         for integer parsing",
-               issue = "22639")]
+    #[unstable(
+        feature = "int_error_matching",
+        reason = "it can be useful to match errors when making error messages \
+                  for integer parsing",
+        issue = "22639"
+    )]
     pub fn kind(&self) -> &IntErrorKind {
         &self.kind
     }
-    #[unstable(feature = "int_error_internals",
-               reason = "available through Error trait and this method should \
-                         not be exposed publicly",
-               issue = "0")]
+    #[unstable(
+        feature = "int_error_internals",
+        reason = "available through Error trait and this method should \
+                  not be exposed publicly",
+        issue = "0"
+    )]
     #[doc(hidden)]
     pub fn __description(&self) -> &str {
         match self.kind {
@@ -5110,131 +4920,3 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use crate::num::dec2flt::ParseFloatError;
-
-// Conversion traits for primitive integer and float types
-// Conversions T -> T are covered by a blanket impl and therefore excluded
-// Some conversions from and to usize/isize are not implemented due to portability concerns
-macro_rules! impl_from {
-    ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
-        #[$attr]
-        #[doc = $doc]
-        impl From<$Small> for $Large {
-            #[inline]
-            fn from(small: $Small) -> $Large {
-                small as $Large
-            }
-        }
-    };
-    ($Small: ty, $Large: ty, #[$attr:meta]) => {
-        impl_from!($Small,
-                   $Large,
-                   #[$attr],
-                   concat!("Converts `",
-                           stringify!($Small),
-                           "` to `",
-                           stringify!($Large),
-                           "` losslessly."));
-    }
-}
-
-macro_rules! impl_from_bool {
-    ($target: ty, #[$attr:meta]) => {
-        impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
-            stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
-values.
-
-# Examples
-
-```
-assert_eq!(", stringify!($target), "::from(true), 1);
-assert_eq!(", stringify!($target), "::from(false), 0);
-```"));
-    };
-}
-
-// Bool -> Any
-impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
-
-// Unsigned -> Unsigned
-impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// Signed -> Signed
-impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// Unsigned -> Signed
-impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
-// which imply that pointer-sized integers must be at least 16 bits:
-// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
-impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-
-// RISC-V defines the possibility of a 128-bit address space (RV128).
-
-// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
-// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
-// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
-
-
-// Note: integers can only be represented with full precision in a float if
-// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
-// Lossy float conversions are not implemented at this time.
-
-// Signed -> Float
-impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-
-// Unsigned -> Float
-impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-
-// Float -> Float
-impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs
index a748ee8..22ba97b 100644
--- a/src/libcore/ops/try.rs
+++ b/src/libcore/ops/try.rs
@@ -5,20 +5,28 @@
 /// extracting those success or failure values from an existing instance and
 /// creating a new instance from a success or failure value.
 #[unstable(feature = "try_trait", issue = "42327")]
-#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
-on(all(
-any(from_method="from_error", from_method="from_ok"),
-from_desugaring="QuestionMark"),
-message="the `?` operator can only be used in {ItemContext} \
-               that returns `Result` or `Option` \
-               (or another type that implements `{Try}`)",
-label="cannot use the `?` operator in {ItemContext} that returns `{Self}`",
-enclosing_scope="this function should return `Result` or `Option` to accept `?`"),
-on(all(from_method="into_result", from_desugaring="QuestionMark"),
-message="the `?` operator can only be applied to values \
-               that implement `{Try}`",
-label="the `?` operator cannot be applied to type `{Self}`")
-))]
+#[cfg_attr(
+    not(bootstrap),
+    rustc_on_unimplemented(
+        on(
+            all(
+                any(from_method = "from_error", from_method = "from_ok"),
+                from_desugaring = "QuestionMark"
+            ),
+            message = "the `?` operator can only be used in {ItemContext} \
+                       that returns `Result` or `Option` \
+                       (or another type that implements `{Try}`)",
+            label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
+            enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
+        ),
+        on(
+            all(from_method = "into_result", from_desugaring = "QuestionMark"),
+            message = "the `?` operator can only be applied to values \
+                       that implement `{Try}`",
+            label = "the `?` operator cannot be applied to type `{Self}`"
+        )
+    )
+)]
 #[doc(alias = "?")]
 pub trait Try {
     /// The type of this value when viewed as successful.
diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs
index 99b372d..e924ee2 100644
--- a/src/libcore/panic.rs
+++ b/src/libcore/panic.rs
@@ -177,6 +177,60 @@
 }
 
 impl<'a> Location<'a> {
+    /// Returns the source location of the caller of this function. If that function's caller is
+    /// annotated then its call location will be returned, and so on up the stack to the first call
+    /// within a non-tracked function body.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(track_caller)]
+    /// use core::panic::Location;
+    ///
+    /// /// Returns the [`Location`] at which it is called.
+    /// #[track_caller]
+    /// fn get_caller_location() -> &'static Location<'static> {
+    ///     Location::caller()
+    /// }
+    ///
+    /// /// Returns a [`Location`] from within this function's definition.
+    /// fn get_just_one_location() -> &'static Location<'static> {
+    ///     get_caller_location()
+    /// }
+    ///
+    /// let fixed_location = get_just_one_location();
+    /// assert_eq!(fixed_location.file(), file!());
+    /// assert_eq!(fixed_location.line(), 15);
+    /// assert_eq!(fixed_location.column(), 5);
+    ///
+    /// // running the same untracked function in a different location gives us the same result
+    /// let second_fixed_location = get_just_one_location();
+    /// assert_eq!(fixed_location.file(), second_fixed_location.file());
+    /// assert_eq!(fixed_location.line(), second_fixed_location.line());
+    /// assert_eq!(fixed_location.column(), second_fixed_location.column());
+    ///
+    /// let this_location = get_caller_location();
+    /// assert_eq!(this_location.file(), file!());
+    /// assert_eq!(this_location.line(), 29);
+    /// assert_eq!(this_location.column(), 21);
+    ///
+    /// // running the tracked function in a different location produces a different value
+    /// let another_location = get_caller_location();
+    /// assert_eq!(this_location.file(), another_location.file());
+    /// assert_ne!(this_location.line(), another_location.line());
+    /// assert_ne!(this_location.column(), another_location.column());
+    /// ```
+    #[cfg(not(bootstrap))]
+    #[unstable(feature = "track_caller",
+               reason = "uses #[track_caller] which is not yet stable",
+               issue = "47809")]
+    #[track_caller]
+    pub const fn caller() -> &'static Location<'static> {
+        crate::intrinsics::caller_location()
+    }
+}
+
+impl<'a> Location<'a> {
     #![unstable(feature = "panic_internals",
                 reason = "internal details of the implementation of the `panic!` \
                           and related macros",
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 5a8d647..4857b11 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -22,10 +22,12 @@
 // ignore-tidy-undocumented-unsafe
 
 #![allow(dead_code, missing_docs)]
-#![unstable(feature = "core_panic",
-            reason = "internal details of the implementation of the `panic!` \
-                      and related macros",
-            issue = "0")]
+#![unstable(
+    feature = "core_panic",
+    reason = "internal details of the implementation of the `panic!` \
+              and related macros",
+    issue = "0"
+)]
 
 use crate::fmt;
 use crate::panic::{Location, PanicInfo};
@@ -33,7 +35,7 @@
 #[cold]
 // never inline unless panic_immediate_abort to avoid code
 // bloat at the call sites as much as possible
-#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
 pub fn panic(expr: &str, location: &Location<'_>) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
@@ -50,7 +52,7 @@
 }
 
 #[cold]
-#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
 fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
@@ -59,13 +61,13 @@
 
     panic_fmt(
         format_args!("index out of bounds: the len is {} but the index is {}", len, index),
-        location
+        location,
     )
 }
 
 #[cold]
-#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
-#[cfg_attr(    feature="panic_immediate_abort" ,inline)]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
 pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         unsafe { super::intrinsics::abort() }
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 88fa718..6a0c5bb 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -376,6 +376,7 @@
 
 use crate::cmp::{self, PartialEq, PartialOrd};
 use crate::fmt;
+use crate::hash::{Hash, Hasher};
 use crate::marker::{Sized, Unpin};
 use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
 
@@ -390,55 +391,78 @@
 /// [`Unpin`]: ../../std/marker/trait.Unpin.html
 /// [`pin` module]: ../../std/pin/index.html
 //
-// Note: the derives below, and the explicit `PartialEq` and `PartialOrd`
-// implementations, are allowed because they all only use `&P`, so they cannot move
-// the value behind `pointer`.
+// Note: the `Clone` derive below causes unsoundness as it's possible to implement
+// `Clone` for mutable references.
+// See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311> for more details.
 #[stable(feature = "pin", since = "1.33.0")]
 #[lang = "pin"]
 #[fundamental]
 #[repr(transparent)]
-#[derive(Copy, Clone, Hash, Eq, Ord)]
+#[derive(Copy, Clone)]
 pub struct Pin<P> {
     pointer: P,
 }
 
-#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")]
-impl<P, Q> PartialEq<Pin<Q>> for Pin<P>
+// The following implementations aren't derived in order to avoid soundness
+// issues. `&self.pointer` should not be accessible to untrusted trait
+// implementations.
+//
+// See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73> for more details.
+
+#[stable(feature = "pin_trait_impls", since = "1.41.0")]
+impl<P: Deref, Q: Deref> PartialEq<Pin<Q>> for Pin<P>
 where
-    P: PartialEq<Q>,
+    P::Target: PartialEq<Q::Target>,
 {
     fn eq(&self, other: &Pin<Q>) -> bool {
-        self.pointer == other.pointer
+        P::Target::eq(self, other)
     }
 
     fn ne(&self, other: &Pin<Q>) -> bool {
-        self.pointer != other.pointer
+        P::Target::ne(self, other)
     }
 }
 
-#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")]
-impl<P, Q> PartialOrd<Pin<Q>> for Pin<P>
+#[stable(feature = "pin_trait_impls", since = "1.41.0")]
+impl<P: Deref<Target: Eq>> Eq for Pin<P> {}
+
+#[stable(feature = "pin_trait_impls", since = "1.41.0")]
+impl<P: Deref, Q: Deref> PartialOrd<Pin<Q>> for Pin<P>
 where
-    P: PartialOrd<Q>,
+    P::Target: PartialOrd<Q::Target>,
 {
     fn partial_cmp(&self, other: &Pin<Q>) -> Option<cmp::Ordering> {
-        self.pointer.partial_cmp(&other.pointer)
+        P::Target::partial_cmp(self, other)
     }
 
     fn lt(&self, other: &Pin<Q>) -> bool {
-        self.pointer < other.pointer
+        P::Target::lt(self, other)
     }
 
     fn le(&self, other: &Pin<Q>) -> bool {
-        self.pointer <= other.pointer
+        P::Target::le(self, other)
     }
 
     fn gt(&self, other: &Pin<Q>) -> bool {
-        self.pointer > other.pointer
+        P::Target::gt(self, other)
     }
 
     fn ge(&self, other: &Pin<Q>) -> bool {
-        self.pointer >= other.pointer
+        P::Target::ge(self, other)
+    }
+}
+
+#[stable(feature = "pin_trait_impls", since = "1.41.0")]
+impl<P: Deref<Target: Ord>> Ord for Pin<P> {
+    fn cmp(&self, other: &Self) -> cmp::Ordering {
+        P::Target::cmp(self, other)
+    }
+}
+
+#[stable(feature = "pin_trait_impls", since = "1.41.0")]
+impl<P: Deref<Target: Hash>> Hash for Pin<P> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        P::Target::hash(self, state);
     }
 }
 
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index 1e051db..24ffa34 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -65,15 +65,16 @@
 //! [`write_volatile`]: ./fn.write_volatile.html
 //! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling
 
+// ignore-tidy-filelength
 // ignore-tidy-undocumented-unsafe
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::intrinsics;
+use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::fmt;
 use crate::hash;
+use crate::intrinsics;
 use crate::mem::{self, MaybeUninit};
-use crate::cmp::Ordering::{self, Less, Equal, Greater};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use crate::intrinsics::copy_nonoverlapping;
@@ -197,7 +198,9 @@
 #[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
-pub const fn null<T>() -> *const T { 0 as *const T }
+pub const fn null<T>() -> *const T {
+    0 as *const T
+}
 
 /// Creates a null mutable raw pointer.
 ///
@@ -212,7 +215,9 @@
 #[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
-pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
+pub const fn null_mut<T>() -> *mut T {
+    0 as *mut T
+}
 
 #[repr(C)]
 pub(crate) union Repr<T> {
@@ -704,9 +709,7 @@
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
 pub unsafe fn read_unaligned<T>(src: *const T) -> T {
     let mut tmp = MaybeUninit::<T>::uninit();
-    copy_nonoverlapping(src as *const u8,
-                        tmp.as_mut_ptr() as *mut u8,
-                        mem::size_of::<T>());
+    copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::<T>());
     tmp.assume_init()
 }
 
@@ -889,9 +892,7 @@
 #[inline]
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
 pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
-    copy_nonoverlapping(&src as *const T as *const u8,
-                        dst as *mut u8,
-                        mem::size_of::<T>());
+    copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>());
     mem::forget(src);
 }
 
@@ -1122,11 +1123,7 @@
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
-        if self.is_null() {
-            None
-        } else {
-            Some(&*self)
-        }
+        if self.is_null() { None } else { Some(&*self) }
     }
 
     /// Calculates the offset from a pointer.
@@ -1182,7 +1179,10 @@
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub unsafe fn offset(self, count: isize) -> *const T where T: Sized {
+    pub unsafe fn offset(self, count: isize) -> *const T
+    where
+        T: Sized,
+    {
         intrinsics::offset(self, count)
     }
 
@@ -1237,10 +1237,11 @@
     /// ```
     #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
     #[inline]
-    pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized {
-        unsafe {
-            intrinsics::arith_offset(self, count)
-        }
+    pub fn wrapping_offset(self, count: isize) -> *const T
+    where
+        T: Sized,
+    {
+        unsafe { intrinsics::arith_offset(self, count) }
     }
 
     /// Calculates the distance between two pointers. The returned value is in
@@ -1308,7 +1309,10 @@
     #[unstable(feature = "ptr_offset_from", issue = "41079")]
     #[rustc_const_unstable(feature = "const_ptr_offset_from")]
     #[inline]
-    pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
+    pub const unsafe fn offset_from(self, origin: *const T) -> isize
+    where
+        T: Sized,
+    {
         let pointee_size = mem::size_of::<T>();
         let ok = 0 < pointee_size && pointee_size <= isize::max_value() as usize;
         // assert that the pointee size is valid in a const eval compatible way
@@ -1353,7 +1357,10 @@
     /// ```
     #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
     #[inline]
-    pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized {
+    pub fn wrapping_offset_from(self, origin: *const T) -> isize
+    where
+        T: Sized,
+    {
         let pointee_size = mem::size_of::<T>();
         assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
 
@@ -1415,7 +1422,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn add(self, count: usize) -> Self
-        where T: Sized,
+    where
+        T: Sized,
     {
         self.offset(count as isize)
     }
@@ -1475,7 +1483,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn sub(self, count: usize) -> Self
-        where T: Sized,
+    where
+        T: Sized,
     {
         self.offset((count as isize).wrapping_neg())
     }
@@ -1529,7 +1538,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub fn wrapping_add(self, count: usize) -> Self
-        where T: Sized,
+    where
+        T: Sized,
     {
         self.wrapping_offset(count as isize)
     }
@@ -1583,7 +1593,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub fn wrapping_sub(self, count: usize) -> Self
-        where T: Sized,
+    where
+        T: Sized,
     {
         self.wrapping_offset((count as isize).wrapping_neg())
     }
@@ -1597,7 +1608,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read(self) -> T
-        where T: Sized,
+    where
+        T: Sized,
     {
         read(self)
     }
@@ -1615,7 +1627,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_volatile(self) -> T
-        where T: Sized,
+    where
+        T: Sized,
     {
         read_volatile(self)
     }
@@ -1631,7 +1644,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_unaligned(self) -> T
-        where T: Sized,
+    where
+        T: Sized,
     {
         read_unaligned(self)
     }
@@ -1647,7 +1661,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to(self, dest: *mut T, count: usize)
-        where T: Sized,
+    where
+        T: Sized,
     {
         copy(self, dest, count)
     }
@@ -1663,7 +1678,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
-        where T: Sized,
+    where
+        T: Sized,
     {
         copy_nonoverlapping(self, dest, count)
     }
@@ -1708,17 +1724,17 @@
     /// # } }
     /// ```
     #[stable(feature = "align_offset", since = "1.36.0")]
-    pub fn align_offset(self, align: usize) -> usize where T: Sized {
+    pub fn align_offset(self, align: usize) -> usize
+    where
+        T: Sized,
+    {
         if !align.is_power_of_two() {
             panic!("align_offset: align is not a power-of-two");
         }
-        unsafe {
-            align_offset(self, align)
-        }
+        unsafe { align_offset(self, align) }
     }
 }
 
-
 #[lang = "mut_ptr"]
 impl<T: ?Sized> *mut T {
     /// Returns `true` if the pointer is null.
@@ -1805,11 +1821,7 @@
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
-        if self.is_null() {
-            None
-        } else {
-            Some(&*self)
-        }
+        if self.is_null() { None } else { Some(&*self) }
     }
 
     /// Calculates the offset from a pointer.
@@ -1865,7 +1877,10 @@
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub unsafe fn offset(self, count: isize) -> *mut T where T: Sized {
+    pub unsafe fn offset(self, count: isize) -> *mut T
+    where
+        T: Sized,
+    {
         intrinsics::offset(self, count) as *mut T
     }
 
@@ -1919,10 +1934,11 @@
     /// ```
     #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
     #[inline]
-    pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized {
-        unsafe {
-            intrinsics::arith_offset(self, count) as *mut T
-        }
+    pub fn wrapping_offset(self, count: isize) -> *mut T
+    where
+        T: Sized,
+    {
+        unsafe { intrinsics::arith_offset(self, count) as *mut T }
     }
 
     /// Returns `None` if the pointer is null, or else returns a mutable
@@ -1967,11 +1983,7 @@
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
     pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
-        if self.is_null() {
-            None
-        } else {
-            Some(&mut *self)
-        }
+        if self.is_null() { None } else { Some(&mut *self) }
     }
 
     /// Calculates the distance between two pointers. The returned value is in
@@ -2039,7 +2051,10 @@
     #[unstable(feature = "ptr_offset_from", issue = "41079")]
     #[rustc_const_unstable(feature = "const_ptr_offset_from")]
     #[inline]
-    pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
+    pub const unsafe fn offset_from(self, origin: *const T) -> isize
+    where
+        T: Sized,
+    {
         (self as *const T).offset_from(origin)
     }
 
@@ -2079,7 +2094,10 @@
     /// ```
     #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
     #[inline]
-    pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized {
+    pub fn wrapping_offset_from(self, origin: *const T) -> isize
+    where
+        T: Sized,
+    {
         (self as *const T).wrapping_offset_from(origin)
     }
 
@@ -2137,7 +2155,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn add(self, count: usize) -> Self
-        where T: Sized,
+    where
+        T: Sized,
     {
         self.offset(count as isize)
     }
@@ -2197,7 +2216,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn sub(self, count: usize) -> Self
-        where T: Sized,
+    where
+        T: Sized,
     {
         self.offset((count as isize).wrapping_neg())
     }
@@ -2251,7 +2271,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub fn wrapping_add(self, count: usize) -> Self
-        where T: Sized,
+    where
+        T: Sized,
     {
         self.wrapping_offset(count as isize)
     }
@@ -2305,7 +2326,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub fn wrapping_sub(self, count: usize) -> Self
-        where T: Sized,
+    where
+        T: Sized,
     {
         self.wrapping_offset((count as isize).wrapping_neg())
     }
@@ -2319,7 +2341,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read(self) -> T
-        where T: Sized,
+    where
+        T: Sized,
     {
         read(self)
     }
@@ -2337,7 +2360,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_volatile(self) -> T
-        where T: Sized,
+    where
+        T: Sized,
     {
         read_volatile(self)
     }
@@ -2353,7 +2377,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_unaligned(self) -> T
-        where T: Sized,
+    where
+        T: Sized,
     {
         read_unaligned(self)
     }
@@ -2369,7 +2394,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to(self, dest: *mut T, count: usize)
-        where T: Sized,
+    where
+        T: Sized,
     {
         copy(self, dest, count)
     }
@@ -2385,7 +2411,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
-        where T: Sized,
+    where
+        T: Sized,
     {
         copy_nonoverlapping(self, dest, count)
     }
@@ -2401,7 +2428,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_from(self, src: *const T, count: usize)
-        where T: Sized,
+    where
+        T: Sized,
     {
         copy(src, self, count)
     }
@@ -2417,7 +2445,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
-        where T: Sized,
+    where
+        T: Sized,
     {
         copy_nonoverlapping(src, self, count)
     }
@@ -2442,7 +2471,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write(self, val: T)
-        where T: Sized,
+    where
+        T: Sized,
     {
         write(self, val)
     }
@@ -2456,7 +2486,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write_bytes(self, val: u8, count: usize)
-        where T: Sized,
+    where
+        T: Sized,
     {
         write_bytes(self, val, count)
     }
@@ -2474,7 +2505,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write_volatile(self, val: T)
-        where T: Sized,
+    where
+        T: Sized,
     {
         write_volatile(self, val)
     }
@@ -2490,7 +2522,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write_unaligned(self, val: T)
-        where T: Sized,
+    where
+        T: Sized,
     {
         write_unaligned(self, val)
     }
@@ -2504,7 +2537,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn replace(self, src: T) -> T
-        where T: Sized,
+    where
+        T: Sized,
     {
         replace(self, src)
     }
@@ -2519,7 +2553,8 @@
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn swap(self, with: *mut T)
-        where T: Sized,
+    where
+        T: Sized,
     {
         swap(self, with)
     }
@@ -2564,13 +2599,14 @@
     /// # } }
     /// ```
     #[stable(feature = "align_offset", since = "1.36.0")]
-    pub fn align_offset(self, align: usize) -> usize where T: Sized {
+    pub fn align_offset(self, align: usize) -> usize
+    where
+        T: Sized,
+    {
         if !align.is_power_of_two() {
             panic!("align_offset: align is not a power-of-two");
         }
-        unsafe {
-            align_offset(self, align)
-        }
+        unsafe { align_offset(self, align) }
     }
 }
 
@@ -2588,7 +2624,7 @@
 /// than trying to adapt this to accommodate that change.
 ///
 /// Any questions go to @nagisa.
-#[lang="align_offset"]
+#[lang = "align_offset"]
 pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
     /// Calculate multiplicative modular inverse of `x` modulo `m`.
     ///
@@ -2628,9 +2664,8 @@
                 // uses e.g., subtraction `mod n`. It is entirely fine to do them `mod
                 // usize::max_value()` instead, because we take the result `mod n` at the end
                 // anyway.
-                inverse = inverse.wrapping_mul(
-                    2usize.wrapping_sub(x.wrapping_mul(inverse))
-                ) & (going_mod - 1);
+                inverse = inverse.wrapping_mul(2usize.wrapping_sub(x.wrapping_mul(inverse)))
+                    & (going_mod - 1);
                 if going_mod > m {
                     return inverse & (m - 1);
                 }
@@ -2689,13 +2724,13 @@
     usize::max_value()
 }
 
-
-
 // Equality for pointers
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *const T {
     #[inline]
-    fn eq(&self, other: &*const T) -> bool { *self == *other }
+    fn eq(&self, other: &*const T) -> bool {
+        *self == *other
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2704,7 +2739,9 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *mut T {
     #[inline]
-    fn eq(&self, other: &*mut T) -> bool { *self == *other }
+    fn eq(&self, other: &*mut T) -> bool {
+        *self == *other
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2890,7 +2927,7 @@
     };
 }
 
-fnptr_impls_args! { }
+fnptr_impls_args! {}
 fnptr_impls_args! { A }
 fnptr_impls_args! { A, B }
 fnptr_impls_args! { A, B, C }
@@ -2927,16 +2964,24 @@
     }
 
     #[inline]
-    fn lt(&self, other: &*const T) -> bool { *self < *other }
+    fn lt(&self, other: &*const T) -> bool {
+        *self < *other
+    }
 
     #[inline]
-    fn le(&self, other: &*const T) -> bool { *self <= *other }
+    fn le(&self, other: &*const T) -> bool {
+        *self <= *other
+    }
 
     #[inline]
-    fn gt(&self, other: &*const T) -> bool { *self > *other }
+    fn gt(&self, other: &*const T) -> bool {
+        *self > *other
+    }
 
     #[inline]
-    fn ge(&self, other: &*const T) -> bool { *self >= *other }
+    fn ge(&self, other: &*const T) -> bool {
+        *self >= *other
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2961,14 +3006,22 @@
     }
 
     #[inline]
-    fn lt(&self, other: &*mut T) -> bool { *self < *other }
+    fn lt(&self, other: &*mut T) -> bool {
+        *self < *other
+    }
 
     #[inline]
-    fn le(&self, other: &*mut T) -> bool { *self <= *other }
+    fn le(&self, other: &*mut T) -> bool {
+        *self <= *other
+    }
 
     #[inline]
-    fn gt(&self, other: &*mut T) -> bool { *self > *other }
+    fn gt(&self, other: &*mut T) -> bool {
+        *self > *other
+    }
 
     #[inline]
-    fn ge(&self, other: &*mut T) -> bool { *self >= *other }
+    fn ge(&self, other: &*mut T) -> bool {
+        *self >= *other
+    }
 }
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 25b7eec..b2a420f 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3371,8 +3371,8 @@
     /// An iterator over the disjoint matches of a pattern within the given string
     /// slice.
     ///
-    /// The pattern can be any type that implements the Pattern trait. Notable
-    /// examples are `&str`, [`char`], and closures that determines the split.
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
     ///
     /// # Iterator behavior
     ///
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index a494274..1037da1 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -296,12 +296,7 @@
     fn next_match(&mut self) -> Option<(usize, usize)> {
         loop {
             // get the haystack after the last character found
-            let bytes = if let Some(slice) = self.haystack.as_bytes()
-                                                 .get(self.finger..self.finger_back) {
-                slice
-            } else {
-                return None;
-            };
+            let bytes = self.haystack.as_bytes().get(self.finger..self.finger_back)?;
             // the last byte of the utf8 encoded needle
             let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
             if let Some(index) = memchr::memchr(last_byte, bytes) {
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 251d49d..6e1aac0 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -27,7 +27,7 @@
 //!
 //! Atomic variables are safe to share between threads (they implement [`Sync`])
 //! but they do not themselves provide the mechanism for sharing and follow the
-//! [threading model](../../../std/thread/index.html#the-threading-model) of rust.
+//! [threading model](../../../std/thread/index.html#the-threading-model) of Rust.
 //! The most common way to share an atomic variable is to put it into an [`Arc`][arc] (an
 //! atomically-reference-counted shared pointer).
 //!
diff --git a/src/libcore/tests/any.rs b/src/libcore/tests/any.rs
index 62bebcb..b0dc990 100644
--- a/src/libcore/tests/any.rs
+++ b/src/libcore/tests/any.rs
@@ -24,11 +24,8 @@
 
 #[test]
 fn any_owning() {
-    let (a, b, c) = (
-        box 5_usize as Box<dyn Any>,
-        box TEST as Box<dyn Any>,
-        box Test as Box<dyn Any>,
-    );
+    let (a, b, c) =
+        (box 5_usize as Box<dyn Any>, box TEST as Box<dyn Any>, box Test as Box<dyn Any>);
 
     assert!(a.is::<usize>());
     assert!(!b.is::<usize>());
@@ -49,12 +46,12 @@
 
     match a.downcast_ref::<usize>() {
         Some(&5) => {}
-        x => panic!("Unexpected value {:?}", x)
+        x => panic!("Unexpected value {:?}", x),
     }
 
     match a.downcast_ref::<Test>() {
         None => {}
-        x => panic!("Unexpected value {:?}", x)
+        x => panic!("Unexpected value {:?}", x),
     }
 }
 
@@ -72,7 +69,7 @@
             assert_eq!(*x, 5);
             *x = 612;
         }
-        x => panic!("Unexpected value {:?}", x)
+        x => panic!("Unexpected value {:?}", x),
     }
 
     match b_r.downcast_mut::<usize>() {
@@ -80,27 +77,27 @@
             assert_eq!(*x, 7);
             *x = 413;
         }
-        x => panic!("Unexpected value {:?}", x)
+        x => panic!("Unexpected value {:?}", x),
     }
 
     match a_r.downcast_mut::<Test>() {
         None => (),
-        x => panic!("Unexpected value {:?}", x)
+        x => panic!("Unexpected value {:?}", x),
     }
 
     match b_r.downcast_mut::<Test>() {
         None => (),
-        x => panic!("Unexpected value {:?}", x)
+        x => panic!("Unexpected value {:?}", x),
     }
 
     match a_r.downcast_mut::<usize>() {
         Some(&mut 612) => {}
-        x => panic!("Unexpected value {:?}", x)
+        x => panic!("Unexpected value {:?}", x),
     }
 
     match b_r.downcast_mut::<usize>() {
         Some(&mut 413) => {}
-        x => panic!("Unexpected value {:?}", x)
+        x => panic!("Unexpected value {:?}", x),
     }
 }
 
diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs
index 4f3b79c..c2a816f 100644
--- a/src/libcore/tests/array.rs
+++ b/src/libcore/tests/array.rs
@@ -41,7 +41,6 @@
     }
 }
 
-
 #[test]
 fn iterator_collect() {
     let arr = [0, 1, 2, 5, 9];
@@ -150,10 +149,7 @@
 #[test]
 fn iterator_debug() {
     let arr = [0, 1, 2, 5, 9];
-    assert_eq!(
-        format!("{:?}", IntoIter::new(arr)),
-        "IntoIter([0, 1, 2, 5, 9])",
-    );
+    assert_eq!(format!("{:?}", IntoIter::new(arr)), "IntoIter([0, 1, 2, 5, 9])",);
 }
 
 #[test]
@@ -168,7 +164,7 @@
     struct Foo<'a>(&'a Cell<usize>);
 
     impl Drop for Foo<'_> {
-       fn drop(&mut self) {
+        fn drop(&mut self) {
             self.0.set(self.0.get() + 1);
         }
     }
diff --git a/src/libcore/tests/ascii.rs b/src/libcore/tests/ascii.rs
index 439ed0c..71275d4 100644
--- a/src/libcore/tests/ascii.rs
+++ b/src/libcore/tests/ascii.rs
@@ -22,10 +22,12 @@
     assert_eq!("hıKß".to_ascii_uppercase(), "HıKß");
 
     for i in 0..501 {
-        let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
-                    else { i };
-        assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(),
-                   (from_u32(upper).unwrap()).to_string());
+        let upper =
+            if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i };
+        assert_eq!(
+            (from_u32(i).unwrap()).to_string().to_ascii_uppercase(),
+            (from_u32(upper).unwrap()).to_string()
+        );
     }
 }
 
@@ -36,23 +38,23 @@
     assert_eq!("HİKß".to_ascii_lowercase(), "hİKß");
 
     for i in 0..501 {
-        let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
-                    else { i };
-        assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(),
-                   (from_u32(lower).unwrap()).to_string());
+        let lower =
+            if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i };
+        assert_eq!(
+            (from_u32(i).unwrap()).to_string().to_ascii_lowercase(),
+            (from_u32(lower).unwrap()).to_string()
+        );
     }
 }
 
 #[test]
 fn test_make_ascii_lower_case() {
     macro_rules! test {
-        ($from: expr, $to: expr) => {
-            {
-                let mut x = $from;
-                x.make_ascii_lowercase();
-                assert_eq!(x, $to);
-            }
-        }
+        ($from: expr, $to: expr) => {{
+            let mut x = $from;
+            x.make_ascii_lowercase();
+            assert_eq!(x, $to);
+        }};
     }
     test!(b'A', b'a');
     test!(b'a', b'a');
@@ -65,17 +67,14 @@
     test!("HİKß".to_string(), "hİKß");
 }
 
-
 #[test]
 fn test_make_ascii_upper_case() {
     macro_rules! test {
-        ($from: expr, $to: expr) => {
-            {
-                let mut x = $from;
-                x.make_ascii_uppercase();
-                assert_eq!(x, $to);
-            }
-        }
+        ($from: expr, $to: expr) => {{
+            let mut x = $from;
+            x.make_ascii_uppercase();
+            assert_eq!(x, $to);
+        }};
     }
     test!(b'a', b'A');
     test!(b'A', b'A');
@@ -88,7 +87,7 @@
     test!("hıKß".to_string(), "HıKß");
 
     let mut x = "Hello".to_string();
-    x[..3].make_ascii_uppercase();  // Test IndexMut on String.
+    x[..3].make_ascii_uppercase(); // Test IndexMut on String.
     assert_eq!(x, "HELlo")
 }
 
@@ -103,10 +102,13 @@
     assert!(!"ß".eq_ignore_ascii_case("s"));
 
     for i in 0..501 {
-        let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
-                    else { i };
-        assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case(
-                &from_u32(lower).unwrap().to_string()));
+        let lower =
+            if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i };
+        assert!(
+            (from_u32(i).unwrap())
+                .to_string()
+                .eq_ignore_ascii_case(&from_u32(lower).unwrap().to_string())
+        );
     }
 }
 
@@ -158,12 +160,14 @@
 
 #[test]
 fn test_is_ascii_alphabetic() {
-    assert_all!(is_ascii_alphabetic,
+    assert_all!(
+        is_ascii_alphabetic,
         "",
         "abcdefghijklmnopqrstuvwxyz",
         "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
     );
-    assert_none!(is_ascii_alphabetic,
+    assert_none!(
+        is_ascii_alphabetic,
         "0123456789",
         "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
         " \t\n\x0c\r",
@@ -177,11 +181,9 @@
 
 #[test]
 fn test_is_ascii_uppercase() {
-    assert_all!(is_ascii_uppercase,
-        "",
-        "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
-    );
-    assert_none!(is_ascii_uppercase,
+    assert_all!(is_ascii_uppercase, "", "ABCDEFGHIJKLMNOQPRSTUVWXYZ",);
+    assert_none!(
+        is_ascii_uppercase,
         "abcdefghijklmnopqrstuvwxyz",
         "0123456789",
         "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
@@ -196,10 +198,9 @@
 
 #[test]
 fn test_is_ascii_lowercase() {
-    assert_all!(is_ascii_lowercase,
-        "abcdefghijklmnopqrstuvwxyz",
-    );
-    assert_none!(is_ascii_lowercase,
+    assert_all!(is_ascii_lowercase, "abcdefghijklmnopqrstuvwxyz",);
+    assert_none!(
+        is_ascii_lowercase,
         "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
         "0123456789",
         "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
@@ -214,13 +215,15 @@
 
 #[test]
 fn test_is_ascii_alphanumeric() {
-    assert_all!(is_ascii_alphanumeric,
+    assert_all!(
+        is_ascii_alphanumeric,
         "",
         "abcdefghijklmnopqrstuvwxyz",
         "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
         "0123456789",
     );
-    assert_none!(is_ascii_alphanumeric,
+    assert_none!(
+        is_ascii_alphanumeric,
         "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
         " \t\n\x0c\r",
         "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -233,11 +236,9 @@
 
 #[test]
 fn test_is_ascii_digit() {
-    assert_all!(is_ascii_digit,
-        "",
-        "0123456789",
-    );
-    assert_none!(is_ascii_digit,
+    assert_all!(is_ascii_digit, "", "0123456789",);
+    assert_none!(
+        is_ascii_digit,
         "abcdefghijklmnopqrstuvwxyz",
         "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
         "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
@@ -252,12 +253,9 @@
 
 #[test]
 fn test_is_ascii_hexdigit() {
-    assert_all!(is_ascii_hexdigit,
-        "",
-        "0123456789",
-        "abcdefABCDEF",
-    );
-    assert_none!(is_ascii_hexdigit,
+    assert_all!(is_ascii_hexdigit, "", "0123456789", "abcdefABCDEF",);
+    assert_none!(
+        is_ascii_hexdigit,
         "ghijklmnopqrstuvwxyz",
         "GHIJKLMNOQPRSTUVWXYZ",
         "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
@@ -272,11 +270,9 @@
 
 #[test]
 fn test_is_ascii_punctuation() {
-    assert_all!(is_ascii_punctuation,
-        "",
-        "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
-    );
-    assert_none!(is_ascii_punctuation,
+    assert_all!(is_ascii_punctuation, "", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",);
+    assert_none!(
+        is_ascii_punctuation,
         "abcdefghijklmnopqrstuvwxyz",
         "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
         "0123456789",
@@ -291,14 +287,16 @@
 
 #[test]
 fn test_is_ascii_graphic() {
-    assert_all!(is_ascii_graphic,
+    assert_all!(
+        is_ascii_graphic,
         "",
         "abcdefghijklmnopqrstuvwxyz",
         "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
         "0123456789",
         "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
     );
-    assert_none!(is_ascii_graphic,
+    assert_none!(
+        is_ascii_graphic,
         " \t\n\x0c\r",
         "\x00\x01\x02\x03\x04\x05\x06\x07",
         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
@@ -310,11 +308,9 @@
 
 #[test]
 fn test_is_ascii_whitespace() {
-    assert_all!(is_ascii_whitespace,
-        "",
-        " \t\n\x0c\r",
-    );
-    assert_none!(is_ascii_whitespace,
+    assert_all!(is_ascii_whitespace, "", " \t\n\x0c\r",);
+    assert_none!(
+        is_ascii_whitespace,
         "abcdefghijklmnopqrstuvwxyz",
         "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
         "0123456789",
@@ -329,7 +325,8 @@
 
 #[test]
 fn test_is_ascii_control() {
-    assert_all!(is_ascii_control,
+    assert_all!(
+        is_ascii_control,
         "",
         "\x00\x01\x02\x03\x04\x05\x06\x07",
         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
@@ -337,7 +334,8 @@
         "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
         "\x7f",
     );
-    assert_none!(is_ascii_control,
+    assert_none!(
+        is_ascii_control,
         "abcdefghijklmnopqrstuvwxyz",
         "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
         "0123456789",
diff --git a/src/libcore/tests/atomic.rs b/src/libcore/tests/atomic.rs
index 05fe846..acbd913 100644
--- a/src/libcore/tests/atomic.rs
+++ b/src/libcore/tests/atomic.rs
@@ -1,5 +1,5 @@
-use core::sync::atomic::*;
 use core::sync::atomic::Ordering::SeqCst;
+use core::sync::atomic::*;
 
 #[test]
 fn bool_() {
@@ -15,7 +15,7 @@
 fn bool_and() {
     let a = AtomicBool::new(true);
     assert_eq!(a.fetch_and(false, SeqCst), true);
-    assert_eq!(a.load(SeqCst),false);
+    assert_eq!(a.load(SeqCst), false);
 }
 
 #[test]
@@ -89,7 +89,7 @@
 
 static S_FALSE: AtomicBool = AtomicBool::new(false);
 static S_TRUE: AtomicBool = AtomicBool::new(true);
-static S_INT: AtomicIsize  = AtomicIsize::new(0);
+static S_INT: AtomicIsize = AtomicIsize::new(0);
 static S_UINT: AtomicUsize = AtomicUsize::new(0);
 
 #[test]
diff --git a/src/libcore/tests/bool.rs b/src/libcore/tests/bool.rs
index 0f1e6e8..e89eb2c 100644
--- a/src/libcore/tests/bool.rs
+++ b/src/libcore/tests/bool.rs
@@ -1,7 +1,7 @@
 #[test]
 fn test_bool_to_option() {
-    assert_eq!(false.then(0), None);
-    assert_eq!(true.then(0), Some(0));
-    assert_eq!(false.then_with(|| 0), None);
-    assert_eq!(true.then_with(|| 0), Some(0));
+    assert_eq!(false.then_some(0), None);
+    assert_eq!(true.then_some(0), Some(0));
+    assert_eq!(false.then(|| 0), None);
+    assert_eq!(true.then(|| 0), Some(0));
 }
diff --git a/src/libcore/tests/cell.rs b/src/libcore/tests/cell.rs
index 4dfd884..801b60b 100644
--- a/src/libcore/tests/cell.rs
+++ b/src/libcore/tests/cell.rs
@@ -236,7 +236,7 @@
     }
     let x = X(RefCell::new((7, 'z')));
     {
-        let mut d: RefMut<'_ ,u32> = x.accessor();
+        let mut d: RefMut<'_, u32> = x.accessor();
         assert_eq!(*d, 7);
         *d += 1;
     }
@@ -250,7 +250,9 @@
     assert_eq!(1, unsafe { *c1.as_ptr() });
 
     let c2: Cell<usize> = Cell::new(0);
-    unsafe { *c2.as_ptr() = 1; }
+    unsafe {
+        *c2.as_ptr() = 1;
+    }
     assert_eq!(1, c2.get());
 
     let r1: RefCell<usize> = RefCell::new(0);
@@ -258,7 +260,9 @@
     assert_eq!(1, unsafe { *r1.as_ptr() });
 
     let r2: RefCell<usize> = RefCell::new(0);
-    unsafe { *r2.as_ptr() = 1; }
+    unsafe {
+        *r2.as_ptr() = 1;
+    }
     assert_eq!(1, *r2.borrow());
 }
 
diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs
index 57e9f4e..c16f540 100644
--- a/src/libcore/tests/char.rs
+++ b/src/libcore/tests/char.rs
@@ -1,6 +1,6 @@
-use std::{char,str};
 use std::convert::TryFrom;
 use std::str::FromStr;
+use std::{char, str};
 
 #[test]
 fn test_convert() {
@@ -143,13 +143,13 @@
 
 #[test]
 fn test_is_numeric() {
-   assert!('2'.is_numeric());
-   assert!('7'.is_numeric());
-   assert!('¾'.is_numeric());
-   assert!(!'c'.is_numeric());
-   assert!(!'i'.is_numeric());
-   assert!(!'z'.is_numeric());
-   assert!(!'Q'.is_numeric());
+    assert!('2'.is_numeric());
+    assert!('7'.is_numeric());
+    assert!('¾'.is_numeric());
+    assert!(!'c'.is_numeric());
+    assert!(!'i'.is_numeric());
+    assert!(!'z'.is_numeric());
+    assert!(!'Q'.is_numeric());
 }
 
 #[test]
@@ -176,9 +176,9 @@
     assert_eq!(string('\u{ff}'), "\u{ff}");
     assert_eq!(string('\u{11b}'), "\u{11b}");
     assert_eq!(string('\u{1d4b6}'), "\u{1d4b6}");
-    assert_eq!(string('\u{301}'), "\\u{301}");     // combining character
-    assert_eq!(string('\u{200b}'),"\\u{200b}");      // zero width space
-    assert_eq!(string('\u{e000}'), "\\u{e000}");     // private use 1
+    assert_eq!(string('\u{301}'), "\\u{301}"); // combining character
+    assert_eq!(string('\u{200b}'), "\\u{200b}"); // zero width space
+    assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1
     assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2
 }
 
@@ -272,8 +272,8 @@
 fn test_decode_utf16() {
     fn check(s: &[u16], expected: &[Result<char, u16>]) {
         let v = char::decode_utf16(s.iter().cloned())
-                     .map(|r| r.map_err(|e| e.unpaired_surrogate()))
-                     .collect::<Vec<_>>();
+            .map(|r| r.map_err(|e| e.unpaired_surrogate()))
+            .collect::<Vec<_>>();
         assert_eq!(v, expected);
     }
     check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]);
diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs
index 5e6778e..56a2f4a 100644
--- a/src/libcore/tests/cmp.rs
+++ b/src/libcore/tests/cmp.rs
@@ -10,6 +10,14 @@
 }
 
 #[test]
+fn test_bool_totalord() {
+    assert_eq!(true.cmp(&false), Greater);
+    assert_eq!(false.cmp(&true), Less);
+    assert_eq!(true.cmp(&true), Equal);
+    assert_eq!(false.cmp(&false), Equal);
+}
+
+#[test]
 fn test_mut_int_totalord() {
     assert_eq!((&mut 5).cmp(&&mut 10), Less);
     assert_eq!((&mut 10).cmp(&&mut 5), Greater);
diff --git a/src/libcore/tests/hash/mod.rs b/src/libcore/tests/hash/mod.rs
index 1000088..ba0220f 100644
--- a/src/libcore/tests/hash/mod.rs
+++ b/src/libcore/tests/hash/mod.rs
@@ -1,7 +1,7 @@
 mod sip;
 
-use std::hash::{Hash, Hasher};
 use std::default::Default;
+use std::hash::{Hash, Hasher};
 use std::rc::Rc;
 
 struct MyHasher {
@@ -20,10 +20,11 @@
             self.hash += *byte as u64;
         }
     }
-    fn finish(&self) -> u64 { self.hash }
+    fn finish(&self) -> u64 {
+        self.hash
+    }
 }
 
-
 #[test]
 fn test_writer_hasher() {
     fn hash<T: Hash>(t: &T) -> u64 {
@@ -52,17 +53,17 @@
     assert_eq!(hash(&'a'), 97);
 
     let s: &str = "a";
-    assert_eq!(hash(& s), 97 + 0xFF);
+    assert_eq!(hash(&s), 97 + 0xFF);
     let s: Box<str> = String::from("a").into_boxed_str();
-    assert_eq!(hash(& s), 97 + 0xFF);
+    assert_eq!(hash(&s), 97 + 0xFF);
     let s: Rc<&str> = Rc::new("a");
     assert_eq!(hash(&s), 97 + 0xFF);
     let cs: &[u8] = &[1, 2, 3];
-    assert_eq!(hash(& cs), 9);
+    assert_eq!(hash(&cs), 9);
     let cs: Box<[u8]> = Box::new([1, 2, 3]);
-    assert_eq!(hash(& cs), 9);
+    assert_eq!(hash(&cs), 9);
     let cs: Rc<[u8]> = Rc::new([1, 2, 3]);
-    assert_eq!(hash(& cs), 9);
+    assert_eq!(hash(&cs), 9);
 
     let ptr = 5_usize as *const i32;
     assert_eq!(hash(&ptr), 5);
@@ -70,24 +71,36 @@
     let ptr = 5_usize as *mut i32;
     assert_eq!(hash(&ptr), 5);
 
+    if cfg!(miri) { // Miri cannot hash pointers
+        return;
+    }
+
     let cs: &mut [u8] = &mut [1, 2, 3];
     let ptr = cs.as_ptr();
     let slice_ptr = cs as *const [u8];
-    #[cfg(not(miri))] // Miri cannot hash pointers
     assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64);
 
     let slice_ptr = cs as *mut [u8];
-    #[cfg(not(miri))] // Miri cannot hash pointers
     assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64);
 }
 
-struct Custom { hash: u64 }
-struct CustomHasher { output: u64 }
+struct Custom {
+    hash: u64,
+}
+struct CustomHasher {
+    output: u64,
+}
 
 impl Hasher for CustomHasher {
-    fn finish(&self) -> u64 { self.output }
-    fn write(&mut self, _: &[u8]) { panic!() }
-    fn write_u64(&mut self, data: u64) { self.output = data; }
+    fn finish(&self) -> u64 {
+        self.output
+    }
+    fn write(&mut self, _: &[u8]) {
+        panic!()
+    }
+    fn write_u64(&mut self, data: u64) {
+        self.output = data;
+    }
 }
 
 impl Default for CustomHasher {
diff --git a/src/libcore/tests/hash/sip.rs b/src/libcore/tests/hash/sip.rs
index b615cfd..0f09554 100644
--- a/src/libcore/tests/hash/sip.rs
+++ b/src/libcore/tests/hash/sip.rs
@@ -2,7 +2,7 @@
 
 use core::hash::{Hash, Hasher};
 use core::hash::{SipHasher, SipHasher13};
-use core::{slice, mem};
+use core::{mem, slice};
 
 // Hash just the bytes of the slice, without length prefix
 struct Bytes<'a>(&'a [u8]);
@@ -16,25 +16,25 @@
 }
 
 macro_rules! u8to64_le {
-    ($buf:expr, $i:expr) =>
-    ($buf[0+$i] as u64 |
-     ($buf[1+$i] as u64) << 8 |
-     ($buf[2+$i] as u64) << 16 |
-     ($buf[3+$i] as u64) << 24 |
-     ($buf[4+$i] as u64) << 32 |
-     ($buf[5+$i] as u64) << 40 |
-     ($buf[6+$i] as u64) << 48 |
-     ($buf[7+$i] as u64) << 56);
-    ($buf:expr, $i:expr, $len:expr) =>
-    ({
+    ($buf:expr, $i:expr) => {
+        $buf[0 + $i] as u64
+            | ($buf[1 + $i] as u64) << 8
+            | ($buf[2 + $i] as u64) << 16
+            | ($buf[3 + $i] as u64) << 24
+            | ($buf[4 + $i] as u64) << 32
+            | ($buf[5 + $i] as u64) << 40
+            | ($buf[6 + $i] as u64) << 48
+            | ($buf[7 + $i] as u64) << 56
+    };
+    ($buf:expr, $i:expr, $len:expr) => {{
         let mut t = 0;
         let mut out = 0;
         while t < $len {
-            out |= ($buf[t+$i] as u64) << t*8;
+            out |= ($buf[t + $i] as u64) << t * 8;
             t += 1;
         }
         out
-    });
+    }};
 }
 
 fn hash_with<H: Hasher, T: Hash>(mut st: H, x: &T) -> u64 {
@@ -49,71 +49,71 @@
 #[test]
 #[allow(unused_must_use)]
 fn test_siphash_1_3() {
-    let vecs : [[u8; 8]; 64] = [
-        [ 0xdc, 0xc4, 0x0f, 0x05, 0x58, 0x01, 0xac, 0xab ],
-        [ 0x93, 0xca, 0x57, 0x7d, 0xf3, 0x9b, 0xf4, 0xc9 ],
-        [ 0x4d, 0xd4, 0xc7, 0x4d, 0x02, 0x9b, 0xcb, 0x82 ],
-        [ 0xfb, 0xf7, 0xdd, 0xe7, 0xb8, 0x0a, 0xf8, 0x8b ],
-        [ 0x28, 0x83, 0xd3, 0x88, 0x60, 0x57, 0x75, 0xcf ],
-        [ 0x67, 0x3b, 0x53, 0x49, 0x2f, 0xd5, 0xf9, 0xde ],
-        [ 0xa7, 0x22, 0x9f, 0xc5, 0x50, 0x2b, 0x0d, 0xc5 ],
-        [ 0x40, 0x11, 0xb1, 0x9b, 0x98, 0x7d, 0x92, 0xd3 ],
-        [ 0x8e, 0x9a, 0x29, 0x8d, 0x11, 0x95, 0x90, 0x36 ],
-        [ 0xe4, 0x3d, 0x06, 0x6c, 0xb3, 0x8e, 0xa4, 0x25 ],
-        [ 0x7f, 0x09, 0xff, 0x92, 0xee, 0x85, 0xde, 0x79 ],
-        [ 0x52, 0xc3, 0x4d, 0xf9, 0xc1, 0x18, 0xc1, 0x70 ],
-        [ 0xa2, 0xd9, 0xb4, 0x57, 0xb1, 0x84, 0xa3, 0x78 ],
-        [ 0xa7, 0xff, 0x29, 0x12, 0x0c, 0x76, 0x6f, 0x30 ],
-        [ 0x34, 0x5d, 0xf9, 0xc0, 0x11, 0xa1, 0x5a, 0x60 ],
-        [ 0x56, 0x99, 0x51, 0x2a, 0x6d, 0xd8, 0x20, 0xd3 ],
-        [ 0x66, 0x8b, 0x90, 0x7d, 0x1a, 0xdd, 0x4f, 0xcc ],
-        [ 0x0c, 0xd8, 0xdb, 0x63, 0x90, 0x68, 0xf2, 0x9c ],
-        [ 0x3e, 0xe6, 0x73, 0xb4, 0x9c, 0x38, 0xfc, 0x8f ],
-        [ 0x1c, 0x7d, 0x29, 0x8d, 0xe5, 0x9d, 0x1f, 0xf2 ],
-        [ 0x40, 0xe0, 0xcc, 0xa6, 0x46, 0x2f, 0xdc, 0xc0 ],
-        [ 0x44, 0xf8, 0x45, 0x2b, 0xfe, 0xab, 0x92, 0xb9 ],
-        [ 0x2e, 0x87, 0x20, 0xa3, 0x9b, 0x7b, 0xfe, 0x7f ],
-        [ 0x23, 0xc1, 0xe6, 0xda, 0x7f, 0x0e, 0x5a, 0x52 ],
-        [ 0x8c, 0x9c, 0x34, 0x67, 0xb2, 0xae, 0x64, 0xf4 ],
-        [ 0x79, 0x09, 0x5b, 0x70, 0x28, 0x59, 0xcd, 0x45 ],
-        [ 0xa5, 0x13, 0x99, 0xca, 0xe3, 0x35, 0x3e, 0x3a ],
-        [ 0x35, 0x3b, 0xde, 0x4a, 0x4e, 0xc7, 0x1d, 0xa9 ],
-        [ 0x0d, 0xd0, 0x6c, 0xef, 0x02, 0xed, 0x0b, 0xfb ],
-        [ 0xf4, 0xe1, 0xb1, 0x4a, 0xb4, 0x3c, 0xd9, 0x88 ],
-        [ 0x63, 0xe6, 0xc5, 0x43, 0xd6, 0x11, 0x0f, 0x54 ],
-        [ 0xbc, 0xd1, 0x21, 0x8c, 0x1f, 0xdd, 0x70, 0x23 ],
-        [ 0x0d, 0xb6, 0xa7, 0x16, 0x6c, 0x7b, 0x15, 0x81 ],
-        [ 0xbf, 0xf9, 0x8f, 0x7a, 0xe5, 0xb9, 0x54, 0x4d ],
-        [ 0x3e, 0x75, 0x2a, 0x1f, 0x78, 0x12, 0x9f, 0x75 ],
-        [ 0x91, 0x6b, 0x18, 0xbf, 0xbe, 0xa3, 0xa1, 0xce ],
-        [ 0x06, 0x62, 0xa2, 0xad, 0xd3, 0x08, 0xf5, 0x2c ],
-        [ 0x57, 0x30, 0xc3, 0xa3, 0x2d, 0x1c, 0x10, 0xb6 ],
-        [ 0xa1, 0x36, 0x3a, 0xae, 0x96, 0x74, 0xf4, 0xb3 ],
-        [ 0x92, 0x83, 0x10, 0x7b, 0x54, 0x57, 0x6b, 0x62 ],
-        [ 0x31, 0x15, 0xe4, 0x99, 0x32, 0x36, 0xd2, 0xc1 ],
-        [ 0x44, 0xd9, 0x1a, 0x3f, 0x92, 0xc1, 0x7c, 0x66 ],
-        [ 0x25, 0x88, 0x13, 0xc8, 0xfe, 0x4f, 0x70, 0x65 ],
-        [ 0xa6, 0x49, 0x89, 0xc2, 0xd1, 0x80, 0xf2, 0x24 ],
-        [ 0x6b, 0x87, 0xf8, 0xfa, 0xed, 0x1c, 0xca, 0xc2 ],
-        [ 0x96, 0x21, 0x04, 0x9f, 0xfc, 0x4b, 0x16, 0xc2 ],
-        [ 0x23, 0xd6, 0xb1, 0x68, 0x93, 0x9c, 0x6e, 0xa1 ],
-        [ 0xfd, 0x14, 0x51, 0x8b, 0x9c, 0x16, 0xfb, 0x49 ],
-        [ 0x46, 0x4c, 0x07, 0xdf, 0xf8, 0x43, 0x31, 0x9f ],
-        [ 0xb3, 0x86, 0xcc, 0x12, 0x24, 0xaf, 0xfd, 0xc6 ],
-        [ 0x8f, 0x09, 0x52, 0x0a, 0xd1, 0x49, 0xaf, 0x7e ],
-        [ 0x9a, 0x2f, 0x29, 0x9d, 0x55, 0x13, 0xf3, 0x1c ],
-        [ 0x12, 0x1f, 0xf4, 0xa2, 0xdd, 0x30, 0x4a, 0xc4 ],
-        [ 0xd0, 0x1e, 0xa7, 0x43, 0x89, 0xe9, 0xfa, 0x36 ],
-        [ 0xe6, 0xbc, 0xf0, 0x73, 0x4c, 0xb3, 0x8f, 0x31 ],
-        [ 0x80, 0xe9, 0xa7, 0x70, 0x36, 0xbf, 0x7a, 0xa2 ],
-        [ 0x75, 0x6d, 0x3c, 0x24, 0xdb, 0xc0, 0xbc, 0xb4 ],
-        [ 0x13, 0x15, 0xb7, 0xfd, 0x52, 0xd8, 0xf8, 0x23 ],
-        [ 0x08, 0x8a, 0x7d, 0xa6, 0x4d, 0x5f, 0x03, 0x8f ],
-        [ 0x48, 0xf1, 0xe8, 0xb7, 0xe5, 0xd0, 0x9c, 0xd8 ],
-        [ 0xee, 0x44, 0xa6, 0xf7, 0xbc, 0xe6, 0xf4, 0xf6 ],
-        [ 0xf2, 0x37, 0x18, 0x0f, 0xd8, 0x9a, 0xc5, 0xae ],
-        [ 0xe0, 0x94, 0x66, 0x4b, 0x15, 0xf6, 0xb2, 0xc3 ],
-        [ 0xa8, 0xb3, 0xbb, 0xb7, 0x62, 0x90, 0x19, 0x9d ]
+    let vecs: [[u8; 8]; 64] = [
+        [0xdc, 0xc4, 0x0f, 0x05, 0x58, 0x01, 0xac, 0xab],
+        [0x93, 0xca, 0x57, 0x7d, 0xf3, 0x9b, 0xf4, 0xc9],
+        [0x4d, 0xd4, 0xc7, 0x4d, 0x02, 0x9b, 0xcb, 0x82],
+        [0xfb, 0xf7, 0xdd, 0xe7, 0xb8, 0x0a, 0xf8, 0x8b],
+        [0x28, 0x83, 0xd3, 0x88, 0x60, 0x57, 0x75, 0xcf],
+        [0x67, 0x3b, 0x53, 0x49, 0x2f, 0xd5, 0xf9, 0xde],
+        [0xa7, 0x22, 0x9f, 0xc5, 0x50, 0x2b, 0x0d, 0xc5],
+        [0x40, 0x11, 0xb1, 0x9b, 0x98, 0x7d, 0x92, 0xd3],
+        [0x8e, 0x9a, 0x29, 0x8d, 0x11, 0x95, 0x90, 0x36],
+        [0xe4, 0x3d, 0x06, 0x6c, 0xb3, 0x8e, 0xa4, 0x25],
+        [0x7f, 0x09, 0xff, 0x92, 0xee, 0x85, 0xde, 0x79],
+        [0x52, 0xc3, 0x4d, 0xf9, 0xc1, 0x18, 0xc1, 0x70],
+        [0xa2, 0xd9, 0xb4, 0x57, 0xb1, 0x84, 0xa3, 0x78],
+        [0xa7, 0xff, 0x29, 0x12, 0x0c, 0x76, 0x6f, 0x30],
+        [0x34, 0x5d, 0xf9, 0xc0, 0x11, 0xa1, 0x5a, 0x60],
+        [0x56, 0x99, 0x51, 0x2a, 0x6d, 0xd8, 0x20, 0xd3],
+        [0x66, 0x8b, 0x90, 0x7d, 0x1a, 0xdd, 0x4f, 0xcc],
+        [0x0c, 0xd8, 0xdb, 0x63, 0x90, 0x68, 0xf2, 0x9c],
+        [0x3e, 0xe6, 0x73, 0xb4, 0x9c, 0x38, 0xfc, 0x8f],
+        [0x1c, 0x7d, 0x29, 0x8d, 0xe5, 0x9d, 0x1f, 0xf2],
+        [0x40, 0xe0, 0xcc, 0xa6, 0x46, 0x2f, 0xdc, 0xc0],
+        [0x44, 0xf8, 0x45, 0x2b, 0xfe, 0xab, 0x92, 0xb9],
+        [0x2e, 0x87, 0x20, 0xa3, 0x9b, 0x7b, 0xfe, 0x7f],
+        [0x23, 0xc1, 0xe6, 0xda, 0x7f, 0x0e, 0x5a, 0x52],
+        [0x8c, 0x9c, 0x34, 0x67, 0xb2, 0xae, 0x64, 0xf4],
+        [0x79, 0x09, 0x5b, 0x70, 0x28, 0x59, 0xcd, 0x45],
+        [0xa5, 0x13, 0x99, 0xca, 0xe3, 0x35, 0x3e, 0x3a],
+        [0x35, 0x3b, 0xde, 0x4a, 0x4e, 0xc7, 0x1d, 0xa9],
+        [0x0d, 0xd0, 0x6c, 0xef, 0x02, 0xed, 0x0b, 0xfb],
+        [0xf4, 0xe1, 0xb1, 0x4a, 0xb4, 0x3c, 0xd9, 0x88],
+        [0x63, 0xe6, 0xc5, 0x43, 0xd6, 0x11, 0x0f, 0x54],
+        [0xbc, 0xd1, 0x21, 0x8c, 0x1f, 0xdd, 0x70, 0x23],
+        [0x0d, 0xb6, 0xa7, 0x16, 0x6c, 0x7b, 0x15, 0x81],
+        [0xbf, 0xf9, 0x8f, 0x7a, 0xe5, 0xb9, 0x54, 0x4d],
+        [0x3e, 0x75, 0x2a, 0x1f, 0x78, 0x12, 0x9f, 0x75],
+        [0x91, 0x6b, 0x18, 0xbf, 0xbe, 0xa3, 0xa1, 0xce],
+        [0x06, 0x62, 0xa2, 0xad, 0xd3, 0x08, 0xf5, 0x2c],
+        [0x57, 0x30, 0xc3, 0xa3, 0x2d, 0x1c, 0x10, 0xb6],
+        [0xa1, 0x36, 0x3a, 0xae, 0x96, 0x74, 0xf4, 0xb3],
+        [0x92, 0x83, 0x10, 0x7b, 0x54, 0x57, 0x6b, 0x62],
+        [0x31, 0x15, 0xe4, 0x99, 0x32, 0x36, 0xd2, 0xc1],
+        [0x44, 0xd9, 0x1a, 0x3f, 0x92, 0xc1, 0x7c, 0x66],
+        [0x25, 0x88, 0x13, 0xc8, 0xfe, 0x4f, 0x70, 0x65],
+        [0xa6, 0x49, 0x89, 0xc2, 0xd1, 0x80, 0xf2, 0x24],
+        [0x6b, 0x87, 0xf8, 0xfa, 0xed, 0x1c, 0xca, 0xc2],
+        [0x96, 0x21, 0x04, 0x9f, 0xfc, 0x4b, 0x16, 0xc2],
+        [0x23, 0xd6, 0xb1, 0x68, 0x93, 0x9c, 0x6e, 0xa1],
+        [0xfd, 0x14, 0x51, 0x8b, 0x9c, 0x16, 0xfb, 0x49],
+        [0x46, 0x4c, 0x07, 0xdf, 0xf8, 0x43, 0x31, 0x9f],
+        [0xb3, 0x86, 0xcc, 0x12, 0x24, 0xaf, 0xfd, 0xc6],
+        [0x8f, 0x09, 0x52, 0x0a, 0xd1, 0x49, 0xaf, 0x7e],
+        [0x9a, 0x2f, 0x29, 0x9d, 0x55, 0x13, 0xf3, 0x1c],
+        [0x12, 0x1f, 0xf4, 0xa2, 0xdd, 0x30, 0x4a, 0xc4],
+        [0xd0, 0x1e, 0xa7, 0x43, 0x89, 0xe9, 0xfa, 0x36],
+        [0xe6, 0xbc, 0xf0, 0x73, 0x4c, 0xb3, 0x8f, 0x31],
+        [0x80, 0xe9, 0xa7, 0x70, 0x36, 0xbf, 0x7a, 0xa2],
+        [0x75, 0x6d, 0x3c, 0x24, 0xdb, 0xc0, 0xbc, 0xb4],
+        [0x13, 0x15, 0xb7, 0xfd, 0x52, 0xd8, 0xf8, 0x23],
+        [0x08, 0x8a, 0x7d, 0xa6, 0x4d, 0x5f, 0x03, 0x8f],
+        [0x48, 0xf1, 0xe8, 0xb7, 0xe5, 0xd0, 0x9c, 0xd8],
+        [0xee, 0x44, 0xa6, 0xf7, 0xbc, 0xe6, 0xf4, 0xf6],
+        [0xf2, 0x37, 0x18, 0x0f, 0xd8, 0x9a, 0xc5, 0xae],
+        [0xe0, 0x94, 0x66, 0x4b, 0x15, 0xf6, 0xb2, 0xc3],
+        [0xa8, 0xb3, 0xbb, 0xb7, 0x62, 0x90, 0x19, 0x9d],
     ];
 
     let k0 = 0x_07_06_05_04_03_02_01_00;
@@ -143,71 +143,71 @@
 #[test]
 #[allow(unused_must_use)]
 fn test_siphash_2_4() {
-    let vecs : [[u8; 8]; 64] = [
-        [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
-        [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
-        [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
-        [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
-        [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
-        [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
-        [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
-        [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
-        [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
-        [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
-        [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
-        [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
-        [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
-        [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
-        [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
-        [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
-        [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
-        [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
-        [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
-        [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
-        [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
-        [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
-        [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
-        [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
-        [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
-        [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
-        [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
-        [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
-        [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
-        [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
-        [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
-        [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
-        [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
-        [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
-        [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
-        [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
-        [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
-        [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
-        [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
-        [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
-        [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
-        [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
-        [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
-        [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
-        [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
-        [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
-        [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
-        [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
-        [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
-        [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
-        [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
-        [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
-        [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
-        [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
-        [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
-        [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
-        [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
-        [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
-        [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
-        [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
-        [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
-        [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
-        [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
-        [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
+    let vecs: [[u8; 8]; 64] = [
+        [0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72],
+        [0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74],
+        [0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d],
+        [0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85],
+        [0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf],
+        [0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18],
+        [0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb],
+        [0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab],
+        [0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93],
+        [0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e],
+        [0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a],
+        [0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4],
+        [0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75],
+        [0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14],
+        [0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7],
+        [0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1],
+        [0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f],
+        [0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69],
+        [0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b],
+        [0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb],
+        [0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe],
+        [0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0],
+        [0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93],
+        [0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8],
+        [0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8],
+        [0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc],
+        [0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17],
+        [0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f],
+        [0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde],
+        [0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6],
+        [0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad],
+        [0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32],
+        [0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71],
+        [0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7],
+        [0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12],
+        [0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15],
+        [0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31],
+        [0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02],
+        [0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca],
+        [0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a],
+        [0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e],
+        [0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad],
+        [0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18],
+        [0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4],
+        [0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9],
+        [0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9],
+        [0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb],
+        [0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0],
+        [0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6],
+        [0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7],
+        [0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee],
+        [0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1],
+        [0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a],
+        [0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81],
+        [0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f],
+        [0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24],
+        [0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7],
+        [0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea],
+        [0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60],
+        [0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66],
+        [0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c],
+        [0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f],
+        [0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5],
+        [0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95],
     ];
 
     let k0 = 0x_07_06_05_04_03_02_01_00;
@@ -320,8 +320,7 @@
     h1.write_u8(0x01u8);
     let mut h2 = SipHasher::new();
     h2.write(unsafe {
-        slice::from_raw_parts(&test_usize as *const _ as *const u8,
-                              mem::size_of::<usize>())
+        slice::from_raw_parts(&test_usize as *const _ as *const u8, mem::size_of::<usize>())
     });
     h2.write(b"bytes");
     h2.write(b"string");
diff --git a/src/libcore/tests/intrinsics.rs b/src/libcore/tests/intrinsics.rs
index 7544c13..fed7c4a 100644
--- a/src/libcore/tests/intrinsics.rs
+++ b/src/libcore/tests/intrinsics.rs
@@ -2,7 +2,8 @@
 
 #[test]
 fn test_typeid_sized_types() {
-    struct X; struct Y(u32);
+    struct X;
+    struct Y(u32);
 
     assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
     assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
@@ -12,7 +13,8 @@
 #[test]
 fn test_typeid_unsized_types() {
     trait Z {}
-    struct X(str); struct Y(dyn Z + 'static);
+    struct X(str);
+    struct Y(dyn Z + 'static);
 
     assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
     assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
diff --git a/src/libcore/tests/manually_drop.rs b/src/libcore/tests/manually_drop.rs
index 49a1c18..77a338d 100644
--- a/src/libcore/tests/manually_drop.rs
+++ b/src/libcore/tests/manually_drop.rs
@@ -13,7 +13,7 @@
     drop(x);
 
     // also test unsizing
-    let x : Box<ManuallyDrop<[TypeWithDrop]>> =
+    let x: Box<ManuallyDrop<[TypeWithDrop]>> =
         Box::new(ManuallyDrop::new([TypeWithDrop, TypeWithDrop]));
     drop(x);
 }
diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs
index f5b2419..59588d9 100644
--- a/src/libcore/tests/mem.rs
+++ b/src/libcore/tests/mem.rs
@@ -96,7 +96,9 @@
 
 #[test]
 fn test_transmute() {
-    trait Foo { fn dummy(&self) { } }
+    trait Foo {
+        fn dummy(&self) {}
+    }
     impl Foo for isize {}
 
     let a = box 100isize as Box<dyn Foo>;
@@ -116,13 +118,13 @@
 fn test_discriminant_send_sync() {
     enum Regular {
         A,
-        B(i32)
+        B(i32),
     }
     enum NotSendSync {
-        A(*const i32)
+        A(*const i32),
     }
 
-    fn is_send_sync<T: Send + Sync>() { }
+    fn is_send_sync<T: Send + Sync>() {}
 
     is_send_sync::<Discriminant<Regular>>();
     is_send_sync::<Discriminant<NotSendSync>>();
diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs
index 77e4846..6c5d198 100644
--- a/src/libcore/tests/nonzero.rs
+++ b/src/libcore/tests/nonzero.rs
@@ -4,9 +4,7 @@
 
 #[test]
 fn test_create_nonzero_instance() {
-    let _a = unsafe {
-        NonZeroU32::new_unchecked(21)
-    };
+    let _a = unsafe { NonZeroU32::new_unchecked(21) };
 }
 
 #[test]
@@ -17,17 +15,15 @@
 
 #[test]
 fn test_match_on_nonzero_option() {
-    let a = Some(unsafe {
-        NonZeroU32::new_unchecked(42)
-    });
+    let a = Some(unsafe { NonZeroU32::new_unchecked(42) });
     match a {
         Some(val) => assert_eq!(val.get(), 42),
-        None => panic!("unexpected None while matching on Some(NonZeroU32(_))")
+        None => panic!("unexpected None while matching on Some(NonZeroU32(_))"),
     }
 
     match unsafe { Some(NonZeroU32::new_unchecked(43)) } {
         Some(val) => assert_eq!(val.get(), 43),
-        None => panic!("unexpected None while matching on Some(NonZeroU32(_))")
+        None => panic!("unexpected None while matching on Some(NonZeroU32(_))"),
     }
 }
 
@@ -45,7 +41,7 @@
     let a = Some(vec![1, 2, 3, 4]);
     match a {
         Some(v) => assert_eq!(v, [1, 2, 3, 4]),
-        None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
+        None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])"),
     }
 }
 
@@ -56,7 +52,7 @@
     let five = Rc::new(5);
     match Some(five) {
         Some(r) => assert_eq!(*r, 5),
-        None => panic!("unexpected None while matching on Some(Rc::new(5))")
+        None => panic!("unexpected None while matching on Some(Rc::new(5))"),
     }
 }
 
@@ -67,7 +63,7 @@
     let five = Arc::new(5);
     match Some(five) {
         Some(a) => assert_eq!(*a, 5),
-        None => panic!("unexpected None while matching on Some(Arc::new(5))")
+        None => panic!("unexpected None while matching on Some(Arc::new(5))"),
     }
 }
 
@@ -85,7 +81,7 @@
     let five = "Five".to_string();
     match Some(five) {
         Some(s) => assert_eq!(s, "Five"),
-        None => panic!("unexpected None while matching on Some(String { ... })")
+        None => panic!("unexpected None while matching on Some(String { ... })"),
     }
 }
 
@@ -100,7 +96,9 @@
 }
 
 macro_rules! atom {
-    ("foo") => { atom::FOO_ATOM }
+    ("foo") => {
+        atom::FOO_ATOM
+    };
 }
 
 #[test]
@@ -108,7 +106,7 @@
     match atom!("foo") {
         // Using as a pattern is supported by the compiler:
         atom!("foo") => {}
-        _ => panic!("Expected the const item as a pattern to match.")
+        _ => panic!("Expected the const item as a pattern to match."),
     }
 }
 
@@ -129,10 +127,7 @@
 #[test]
 fn test_from_str() {
     assert_eq!("123".parse::<NonZeroU8>(), Ok(NonZeroU8::new(123).unwrap()));
-    assert_eq!(
-        "0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
-        Some(IntErrorKind::Zero)
-    );
+    assert_eq!("0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()), Some(IntErrorKind::Zero));
     assert_eq!(
         "-1".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
         Some(IntErrorKind::InvalidDigit)
diff --git a/src/libcore/tests/num/bignum.rs b/src/libcore/tests/num/bignum.rs
index 50a3ec0..1457064 100644
--- a/src/libcore/tests/num/bignum.rs
+++ b/src/libcore/tests/num/bignum.rs
@@ -70,7 +70,7 @@
 fn test_mul_small() {
     assert_eq!(*Big::from_small(7).mul_small(5), Big::from_small(35));
     assert_eq!(*Big::from_small(0xff).mul_small(0xff), Big::from_u64(0xfe01));
-    assert_eq!(*Big::from_u64(0xffffff/13).mul_small(13), Big::from_u64(0xffffff));
+    assert_eq!(*Big::from_u64(0xffffff / 13).mul_small(13), Big::from_u64(0xffffff));
 }
 
 #[test]
@@ -134,7 +134,7 @@
     assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), Big::from_u64(0x4edc2));
     assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), Big::from_u64(0x7530c3));
     assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), Big::from_u64(0x3ae13e));
-    assert_eq!(*Big::from_u64(0xffffff/13).mul_digits(&[13]), Big::from_u64(0xffffff));
+    assert_eq!(*Big::from_u64(0xffffff / 13).mul_digits(&[13]), Big::from_u64(0xffffff));
     assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), Big::from_u64(0xffffff));
 }
 
@@ -156,10 +156,14 @@
     assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), (Big::from_small(17), 0));
     assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), (Big::from_small(15), 15));
     assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), (Big::from_small(0), 3));
-    assert_eq!(as_val(Big::from_u64(0xffffff).div_rem_small(123)),
-               (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8));
-    assert_eq!(as_val(Big::from_u64(0x10000).div_rem_small(123)),
-               (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8));
+    assert_eq!(
+        as_val(Big::from_u64(0xffffff).div_rem_small(123)),
+        (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8)
+    );
+    assert_eq!(
+        as_val(Big::from_u64(0x10000).div_rem_small(123)),
+        (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8)
+    );
 }
 
 #[test]
diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs
index 46eacb4..6bb348f 100644
--- a/src/libcore/tests/num/dec2flt/mod.rs
+++ b/src/libcore/tests/num/dec2flt/mod.rs
@@ -1,6 +1,6 @@
 #![allow(overflowing_literals)]
 
-use std::{i64, f32, f64};
+use std::{f32, f64, i64};
 
 mod parse;
 mod rawfp;
@@ -9,7 +9,7 @@
 // to be correct) and see if those strings are parsed back to the value of the literal.
 // Requires a *polymorphic literal*, i.e., one that can serve as f64 as well as f32.
 macro_rules! test_literal {
-    ($x: expr) => ({
+    ($x: expr) => {{
         let x32: f32 = $x;
         let x64: f64 = $x;
         let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)];
@@ -20,7 +20,7 @@
             assert_eq!(neg_input.parse(), Ok(-x64));
             assert_eq!(neg_input.parse(), Ok(-x32));
         }
-    })
+    }};
 }
 
 #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
@@ -31,7 +31,11 @@
     test_literal!(0.1);
     test_literal!(12345.);
     test_literal!(0.9999999);
-    #[cfg(not(miri))] // Miri is too slow
+
+    if cfg!(miri) { // Miri is too slow
+        return;
+    }
+
     test_literal!(2.2250738585072014e-308);
 }
 
@@ -53,7 +57,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn subnormals() {
     test_literal!(5e-324);
     test_literal!(91e-324);
@@ -65,7 +69,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn infinity() {
     test_literal!(1e400);
     test_literal!(1e309);
@@ -77,9 +81,12 @@
 fn zero() {
     test_literal!(0.0);
     test_literal!(1e-325);
-    #[cfg(not(miri))] // Miri is too slow
+
+    if cfg!(miri) { // Miri is too slow
+        return;
+    }
+
     test_literal!(1e-326);
-    #[cfg(not(miri))] // Miri is too slow
     test_literal!(1e-500);
 }
 
diff --git a/src/libcore/tests/num/dec2flt/parse.rs b/src/libcore/tests/num/dec2flt/parse.rs
index 1eac484..bb7e51d 100644
--- a/src/libcore/tests/num/dec2flt/parse.rs
+++ b/src/libcore/tests/num/dec2flt/parse.rs
@@ -1,5 +1,5 @@
-use core::num::dec2flt::parse::{Decimal, parse_decimal};
-use core::num::dec2flt::parse::ParseResult::{Valid, Invalid};
+use core::num::dec2flt::parse::ParseResult::{Invalid, Valid};
+use core::num::dec2flt::parse::{parse_decimal, Decimal};
 
 #[test]
 fn missing_pieces() {
diff --git a/src/libcore/tests/num/dec2flt/rawfp.rs b/src/libcore/tests/num/dec2flt/rawfp.rs
index 747c1bf..665fb6b 100644
--- a/src/libcore/tests/num/dec2flt/rawfp.rs
+++ b/src/libcore/tests/num/dec2flt/rawfp.rs
@@ -1,8 +1,8 @@
+use core::num::dec2flt::rawfp::RawFloat;
+use core::num::dec2flt::rawfp::{fp_to_float, next_float, prev_float, round_normal};
+use core::num::diy_float::Fp;
 use std::f32;
 use std::f64;
-use core::num::diy_float::Fp;
-use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal};
-use core::num::dec2flt::rawfp::RawFloat;
 
 fn integer_decode(f: f64) -> (u64, i16, i8) {
     RawFloat::integer_decode(f)
@@ -53,16 +53,23 @@
     assert_eq!(fp_to_float::<f64>(Fp { f: 4, e: -3 }), 0.5);
 }
 
-const SOME_FLOATS: [f64; 9] =
-    [0.1f64, 33.568, 42.1e-5, 777.0e9, 1.1111, 0.347997,
-     9843579834.35892, 12456.0e-150, 54389573.0e-150];
-
+const SOME_FLOATS: [f64; 9] = [
+    0.1f64,
+    33.568,
+    42.1e-5,
+    777.0e9,
+    1.1111,
+    0.347997,
+    9843579834.35892,
+    12456.0e-150,
+    54389573.0e-150,
+];
 
 #[test]
 fn human_f64_roundtrip() {
     for &x in &SOME_FLOATS {
         let (f, e, _) = integer_decode(x);
-        let fp = Fp { f: f, e: e};
+        let fp = Fp { f: f, e: e };
         assert_eq!(fp_to_float::<f64>(fp), x);
     }
 }
diff --git a/src/libcore/tests/num/flt2dec/estimator.rs b/src/libcore/tests/num/flt2dec/estimator.rs
index c514517..8ee06d8 100644
--- a/src/libcore/tests/num/flt2dec/estimator.rs
+++ b/src/libcore/tests/num/flt2dec/estimator.rs
@@ -3,14 +3,24 @@
 #[test]
 fn test_estimate_scaling_factor() {
     macro_rules! assert_almost_eq {
-        ($actual:expr, $expected:expr) => ({
+        ($actual:expr, $expected:expr) => {{
             let actual = $actual;
             let expected = $expected;
-            println!("{} - {} = {} - {} = {}", stringify!($expected), stringify!($actual),
-                     expected, actual, expected - actual);
-            assert!(expected == actual || expected == actual + 1,
-                    "expected {}, actual {}", expected, actual);
-        })
+            println!(
+                "{} - {} = {} - {} = {}",
+                stringify!($expected),
+                stringify!($actual),
+                expected,
+                actual,
+                expected - actual
+            );
+            assert!(
+                expected == actual || expected == actual + 1,
+                "expected {}, actual {}",
+                expected,
+                actual
+            );
+        }};
     }
 
     assert_almost_eq!(estimate_scaling_factor(1, 0), 0);
diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs
index f85369c..2f94ea2 100644
--- a/src/libcore/tests/num/flt2dec/mod.rs
+++ b/src/libcore/tests/num/flt2dec/mod.rs
@@ -256,7 +256,6 @@
     check_shortest!(f(minf32) => b"1", -44);
 }
 
-#[cfg(not(miri))] // Miri is too slow
 pub fn f32_exact_sanity_test<F>(mut f: F)
         where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
     let minf32 = ldexp_f32(1.0, -149);
@@ -362,7 +361,6 @@
     check_shortest!(f(minf64) => b"5", -323);
 }
 
-#[cfg(not(miri))] // Miri is too slow
 pub fn f64_exact_sanity_test<F>(mut f: F)
         where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
     let minf64 = ldexp_f64(1.0, -1074);
diff --git a/src/libcore/tests/num/flt2dec/random.rs b/src/libcore/tests/num/flt2dec/random.rs
index d954379..ecdfc4b 100644
--- a/src/libcore/tests/num/flt2dec/random.rs
+++ b/src/libcore/tests/num/flt2dec/random.rs
@@ -3,27 +3,28 @@
 use std::i16;
 use std::str;
 
-use core::num::flt2dec::MAX_SIG_DIGITS;
 use core::num::flt2dec::strategy::grisu::format_exact_opt;
 use core::num::flt2dec::strategy::grisu::format_shortest_opt;
-use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
+use core::num::flt2dec::MAX_SIG_DIGITS;
+use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
 
-use rand::SeedableRng;
-use rand::rngs::StdRng;
 use rand::distributions::{Distribution, Uniform};
+use rand::rngs::StdRng;
+use rand::SeedableRng;
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
         FullDecoded::Finite(decoded) => decoded,
-        full_decoded => panic!("expected finite, got {:?} instead", full_decoded)
+        full_decoded => panic!("expected finite, got {:?} instead", full_decoded),
     }
 }
 
-
 fn iterate<F, G, V>(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize)
-        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
-              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
-              V: FnMut(usize) -> Decoded {
+where
+    F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+    G: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
+    V: FnMut(usize) -> Decoded,
+{
     assert!(k <= 1024);
 
     let mut npassed = 0; // f(x) = Some(g(x))
@@ -31,8 +32,14 @@
 
     for i in 0..n {
         if (i & 0xfffff) == 0 {
-            println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})",
-                     i, n, nignored, npassed, i - nignored - npassed);
+            println!(
+                "in progress, {:x}/{:x} (ignored={} passed={} failed={})",
+                i,
+                n,
+                nignored,
+                npassed,
+                i - nignored - npassed
+            );
         }
 
         let decoded = v(i);
@@ -43,27 +50,47 @@
             if e1 == e2 && &buf1[..len1] == &buf2[..len2] {
                 npassed += 1;
             } else {
-                println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}",
-                         i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1,
-                                        str::from_utf8(&buf2[..len2]).unwrap(), e2);
+                println!(
+                    "equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}",
+                    i,
+                    n,
+                    decoded,
+                    str::from_utf8(&buf1[..len1]).unwrap(),
+                    e1,
+                    str::from_utf8(&buf2[..len2]).unwrap(),
+                    e2
+                );
             }
         } else {
             nignored += 1;
         }
     }
-    println!("{}({}): done, ignored={} passed={} failed={}",
-             func, k, nignored, npassed, n - nignored - npassed);
-    assert!(nignored + npassed == n,
-            "{}({}): {} out of {} values returns an incorrect value!",
-            func, k, n - nignored - npassed, n);
+    println!(
+        "{}({}): done, ignored={} passed={} failed={}",
+        func,
+        k,
+        nignored,
+        npassed,
+        n - nignored - npassed
+    );
+    assert!(
+        nignored + npassed == n,
+        "{}({}): {} out of {} values returns an incorrect value!",
+        func,
+        k,
+        n - nignored - npassed,
+        n
+    );
     (npassed, nignored)
 }
 
 pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
-        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
-              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+where
+    F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+    G: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
+{
     if cfg!(target_os = "emscripten") {
-        return // using rng pulls in i128 support, which doesn't work
+        return; // using rng pulls in i128 support, which doesn't work
     }
     let mut rng = StdRng::from_entropy();
     let f32_range = Uniform::new(0x0000_0001u32, 0x7f80_0000);
@@ -74,10 +101,12 @@
 }
 
 pub fn f64_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
-        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
-              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+where
+    F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+    G: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
+{
     if cfg!(target_os = "emscripten") {
-        return // using rng pulls in i128 support, which doesn't work
+        return; // using rng pulls in i128 support, which doesn't work
     }
     let mut rng = StdRng::from_entropy();
     let f64_range = Uniform::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000);
@@ -88,8 +117,10 @@
 }
 
 pub fn f32_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
-        where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
-              G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+where
+    F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>,
+    G: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
+{
     // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values,
     // so why not simply testing all of them?
     //
@@ -97,12 +128,11 @@
     // but with `-C opt-level=3 -C lto` this only takes about an hour or so.
 
     // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e., all finite ranges
-    let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test",
-                                      k, 0x7f7f_ffff, f, g, |i: usize| {
-
-        let x = f32::from_bits(i as u32 + 1);
-        decode_finite(x)
-    });
+    let (npassed, nignored) =
+        iterate("f32_exhaustive_equivalence_test", k, 0x7f7f_ffff, f, g, |i: usize| {
+            let x = f32::from_bits(i as u32 + 1);
+            decode_finite(x)
+        });
     assert_eq!((npassed, nignored), (2121451881, 17643158));
 }
 
@@ -118,7 +148,8 @@
     f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, N);
 }
 
-#[test] #[ignore] // it is too expensive
+#[test]
+#[ignore] // it is too expensive
 fn shortest_f32_exhaustive_equivalence_test() {
     // it is hard to directly test the optimality of the output, but we can at least test if
     // two different algorithms agree to each other.
@@ -131,13 +162,13 @@
     f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS);
 }
 
-#[test] #[ignore] // it is too expensive
+#[test]
+#[ignore] // it is too expensive
 fn shortest_f64_hard_random_equivalence_test() {
     // this again probably has to use appropriate rustc flags.
 
     use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
-    f64_random_equivalence_test(format_shortest_opt, fallback,
-                                         MAX_SIG_DIGITS, 100_000_000);
+    f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 100_000_000);
 }
 
 #[test]
@@ -149,8 +180,12 @@
     const N: usize = 3;
 
     for k in 1..21 {
-        f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
-                                             |d, buf| fallback(d, buf, i16::MIN), k, N);
+        f32_random_equivalence_test(
+            |d, buf| format_exact_opt(d, buf, i16::MIN),
+            |d, buf| fallback(d, buf, i16::MIN),
+            k,
+            N,
+        );
     }
 }
 
@@ -163,7 +198,11 @@
     const N: usize = 3;
 
     for k in 1..21 {
-        f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN),
-                                             |d, buf| fallback(d, buf, i16::MIN), k, N);
+        f64_random_equivalence_test(
+            |d, buf| format_exact_opt(d, buf, i16::MIN),
+            |d, buf| fallback(d, buf, i16::MIN),
+            k,
+            N,
+        );
     }
 }
diff --git a/src/libcore/tests/num/flt2dec/strategy/dragon.rs b/src/libcore/tests/num/flt2dec/strategy/dragon.rs
index 0c545b4..3d985c6 100644
--- a/src/libcore/tests/num/flt2dec/strategy/dragon.rs
+++ b/src/libcore/tests/num/flt2dec/strategy/dragon.rs
@@ -22,7 +22,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn exact_sanity_test() {
     // This test ends up running what I can only assume is some corner-ish case
     // of the `exp2` library function, defined in whatever C runtime we're
diff --git a/src/libcore/tests/num/flt2dec/strategy/grisu.rs b/src/libcore/tests/num/flt2dec/strategy/grisu.rs
index f8bdddf..ff8373c 100644
--- a/src/libcore/tests/num/flt2dec/strategy/grisu.rs
+++ b/src/libcore/tests/num/flt2dec/strategy/grisu.rs
@@ -6,12 +6,18 @@
     assert_eq!(CACHED_POW10.first().unwrap().1, CACHED_POW10_FIRST_E);
     assert_eq!(CACHED_POW10.last().unwrap().1, CACHED_POW10_LAST_E);
 
-    for e in -1137..961 { // full range for f64
+    for e in -1137..961 {
+        // full range for f64
         let low = ALPHA - e - 64;
         let high = GAMMA - e - 64;
         let (_k, cached) = cached_power(low, high);
-        assert!(low <= cached.e && cached.e <= high,
-                "cached_power({}, {}) = {:?} is incorrect", low, high, cached);
+        assert!(
+            low <= cached.e && cached.e <= high,
+            "cached_power({}, {}) = {:?} is incorrect",
+            low,
+            high,
+            cached
+        );
     }
 }
 
@@ -26,7 +32,6 @@
     }
 }
 
-
 #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
 #[test]
 fn shortest_sanity_test() {
@@ -36,7 +41,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn exact_sanity_test() {
     // See comments in dragon.rs's exact_sanity_test for why this test is
     // ignored on MSVC
diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs
index 0475aeb..4a44b5f 100644
--- a/src/libcore/tests/num/int_macros.rs
+++ b/src/libcore/tests/num/int_macros.rs
@@ -1,240 +1,241 @@
-macro_rules! int_module { ($T:ident, $T_i:ident) => (
-#[cfg(test)]
-mod tests {
-    use core::$T_i::*;
-    use core::isize;
-    use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
-    use core::mem;
+macro_rules! int_module {
+    ($T:ident, $T_i:ident) => {
+        #[cfg(test)]
+        mod tests {
+            use core::isize;
+            use core::mem;
+            use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
+            use core::$T_i::*;
 
-    use crate::num;
+            use crate::num;
 
-    #[test]
-    fn test_overflows() {
-        assert!(MAX > 0);
-        assert!(MIN <= 0);
-        assert_eq!(MIN + MAX + 1, 0);
-    }
+            #[test]
+            fn test_overflows() {
+                assert!(MAX > 0);
+                assert!(MIN <= 0);
+                assert_eq!(MIN + MAX + 1, 0);
+            }
 
-    #[test]
-    fn test_num() {
-        num::test_num(10 as $T, 2 as $T);
-    }
+            #[test]
+            fn test_num() {
+                num::test_num(10 as $T, 2 as $T);
+            }
 
-    #[test]
-    fn test_rem_euclid() {
-        assert_eq!((-1 as $T).rem_euclid(MIN), MAX);
-    }
+            #[test]
+            fn test_rem_euclid() {
+                assert_eq!((-1 as $T).rem_euclid(MIN), MAX);
+            }
 
-    #[test]
-    pub fn test_abs() {
-        assert_eq!((1 as $T).abs(), 1 as $T);
-        assert_eq!((0 as $T).abs(), 0 as $T);
-        assert_eq!((-1 as $T).abs(), 1 as $T);
-    }
+            #[test]
+            pub fn test_abs() {
+                assert_eq!((1 as $T).abs(), 1 as $T);
+                assert_eq!((0 as $T).abs(), 0 as $T);
+                assert_eq!((-1 as $T).abs(), 1 as $T);
+            }
 
-    #[test]
-    fn test_signum() {
-        assert_eq!((1 as $T).signum(), 1 as $T);
-        assert_eq!((0 as $T).signum(), 0 as $T);
-        assert_eq!((-0 as $T).signum(), 0 as $T);
-        assert_eq!((-1 as $T).signum(), -1 as $T);
-    }
+            #[test]
+            fn test_signum() {
+                assert_eq!((1 as $T).signum(), 1 as $T);
+                assert_eq!((0 as $T).signum(), 0 as $T);
+                assert_eq!((-0 as $T).signum(), 0 as $T);
+                assert_eq!((-1 as $T).signum(), -1 as $T);
+            }
 
-    #[test]
-    fn test_is_positive() {
-        assert!((1 as $T).is_positive());
-        assert!(!(0 as $T).is_positive());
-        assert!(!(-0 as $T).is_positive());
-        assert!(!(-1 as $T).is_positive());
-    }
+            #[test]
+            fn test_is_positive() {
+                assert!((1 as $T).is_positive());
+                assert!(!(0 as $T).is_positive());
+                assert!(!(-0 as $T).is_positive());
+                assert!(!(-1 as $T).is_positive());
+            }
 
-    #[test]
-    fn test_is_negative() {
-        assert!(!(1 as $T).is_negative());
-        assert!(!(0 as $T).is_negative());
-        assert!(!(-0 as $T).is_negative());
-        assert!((-1 as $T).is_negative());
-    }
+            #[test]
+            fn test_is_negative() {
+                assert!(!(1 as $T).is_negative());
+                assert!(!(0 as $T).is_negative());
+                assert!(!(-0 as $T).is_negative());
+                assert!((-1 as $T).is_negative());
+            }
 
-    #[test]
-    fn test_bitwise_operators() {
-        assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T));
-        assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T));
-        assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T));
-        assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1));
-        assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1));
-        assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not());
-    }
+            #[test]
+            fn test_bitwise_operators() {
+                assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T));
+                assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T));
+                assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T));
+                assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1));
+                assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1));
+                assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not());
+            }
 
-    const A: $T = 0b0101100;
-    const B: $T = 0b0100001;
-    const C: $T = 0b1111001;
+            const A: $T = 0b0101100;
+            const B: $T = 0b0100001;
+            const C: $T = 0b1111001;
 
-    const _0: $T = 0;
-    const _1: $T = !0;
+            const _0: $T = 0;
+            const _1: $T = !0;
 
-    #[test]
-    fn test_count_ones() {
-        assert_eq!(A.count_ones(), 3);
-        assert_eq!(B.count_ones(), 2);
-        assert_eq!(C.count_ones(), 5);
-    }
+            #[test]
+            fn test_count_ones() {
+                assert_eq!(A.count_ones(), 3);
+                assert_eq!(B.count_ones(), 2);
+                assert_eq!(C.count_ones(), 5);
+            }
 
-    #[test]
-    fn test_count_zeros() {
-        let bits = mem::size_of::<$T>() * 8;
-        assert_eq!(A.count_zeros(), bits as u32 - 3);
-        assert_eq!(B.count_zeros(), bits as u32 - 2);
-        assert_eq!(C.count_zeros(), bits as u32 - 5);
-    }
+            #[test]
+            fn test_count_zeros() {
+                let bits = mem::size_of::<$T>() * 8;
+                assert_eq!(A.count_zeros(), bits as u32 - 3);
+                assert_eq!(B.count_zeros(), bits as u32 - 2);
+                assert_eq!(C.count_zeros(), bits as u32 - 5);
+            }
 
-    #[test]
-    fn test_rotate() {
-        assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
-        assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
-        assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+            #[test]
+            fn test_rotate() {
+                assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+                assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+                assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
 
-        // Rotating these should make no difference
-        //
-        // We test using 124 bits because to ensure that overlong bit shifts do
-        // not cause undefined behaviour. See #10183.
-        assert_eq!(_0.rotate_left(124), _0);
-        assert_eq!(_1.rotate_left(124), _1);
-        assert_eq!(_0.rotate_right(124), _0);
-        assert_eq!(_1.rotate_right(124), _1);
+                // Rotating these should make no difference
+                //
+                // We test using 124 bits because to ensure that overlong bit shifts do
+                // not cause undefined behaviour. See #10183.
+                assert_eq!(_0.rotate_left(124), _0);
+                assert_eq!(_1.rotate_left(124), _1);
+                assert_eq!(_0.rotate_right(124), _0);
+                assert_eq!(_1.rotate_right(124), _1);
 
-        // Rotating by 0 should have no effect
-        assert_eq!(A.rotate_left(0), A);
-        assert_eq!(B.rotate_left(0), B);
-        assert_eq!(C.rotate_left(0), C);
-        // Rotating by a multiple of word size should also have no effect
-        assert_eq!(A.rotate_left(64), A);
-        assert_eq!(B.rotate_left(64), B);
-        assert_eq!(C.rotate_left(64), C);
-    }
+                // Rotating by 0 should have no effect
+                assert_eq!(A.rotate_left(0), A);
+                assert_eq!(B.rotate_left(0), B);
+                assert_eq!(C.rotate_left(0), C);
+                // Rotating by a multiple of word size should also have no effect
+                assert_eq!(A.rotate_left(64), A);
+                assert_eq!(B.rotate_left(64), B);
+                assert_eq!(C.rotate_left(64), C);
+            }
 
-    #[test]
-    fn test_swap_bytes() {
-        assert_eq!(A.swap_bytes().swap_bytes(), A);
-        assert_eq!(B.swap_bytes().swap_bytes(), B);
-        assert_eq!(C.swap_bytes().swap_bytes(), C);
+            #[test]
+            fn test_swap_bytes() {
+                assert_eq!(A.swap_bytes().swap_bytes(), A);
+                assert_eq!(B.swap_bytes().swap_bytes(), B);
+                assert_eq!(C.swap_bytes().swap_bytes(), C);
 
-        // Swapping these should make no difference
-        assert_eq!(_0.swap_bytes(), _0);
-        assert_eq!(_1.swap_bytes(), _1);
-    }
+                // Swapping these should make no difference
+                assert_eq!(_0.swap_bytes(), _0);
+                assert_eq!(_1.swap_bytes(), _1);
+            }
 
-    #[test]
-    fn test_le() {
-        assert_eq!($T::from_le(A.to_le()), A);
-        assert_eq!($T::from_le(B.to_le()), B);
-        assert_eq!($T::from_le(C.to_le()), C);
-        assert_eq!($T::from_le(_0), _0);
-        assert_eq!($T::from_le(_1), _1);
-        assert_eq!(_0.to_le(), _0);
-        assert_eq!(_1.to_le(), _1);
-    }
+            #[test]
+            fn test_le() {
+                assert_eq!($T::from_le(A.to_le()), A);
+                assert_eq!($T::from_le(B.to_le()), B);
+                assert_eq!($T::from_le(C.to_le()), C);
+                assert_eq!($T::from_le(_0), _0);
+                assert_eq!($T::from_le(_1), _1);
+                assert_eq!(_0.to_le(), _0);
+                assert_eq!(_1.to_le(), _1);
+            }
 
-    #[test]
-    fn test_be() {
-        assert_eq!($T::from_be(A.to_be()), A);
-        assert_eq!($T::from_be(B.to_be()), B);
-        assert_eq!($T::from_be(C.to_be()), C);
-        assert_eq!($T::from_be(_0), _0);
-        assert_eq!($T::from_be(_1), _1);
-        assert_eq!(_0.to_be(), _0);
-        assert_eq!(_1.to_be(), _1);
-    }
+            #[test]
+            fn test_be() {
+                assert_eq!($T::from_be(A.to_be()), A);
+                assert_eq!($T::from_be(B.to_be()), B);
+                assert_eq!($T::from_be(C.to_be()), C);
+                assert_eq!($T::from_be(_0), _0);
+                assert_eq!($T::from_be(_1), _1);
+                assert_eq!(_0.to_be(), _0);
+                assert_eq!(_1.to_be(), _1);
+            }
 
-    #[test]
-    fn test_signed_checked_div() {
-        assert_eq!((10 as $T).checked_div(2), Some(5));
-        assert_eq!((5 as $T).checked_div(0), None);
-        assert_eq!(isize::MIN.checked_div(-1), None);
-    }
+            #[test]
+            fn test_signed_checked_div() {
+                assert_eq!((10 as $T).checked_div(2), Some(5));
+                assert_eq!((5 as $T).checked_div(0), None);
+                assert_eq!(isize::MIN.checked_div(-1), None);
+            }
 
-    #[test]
-    fn test_saturating_abs() {
-        assert_eq!((0 as $T).saturating_abs(), 0);
-        assert_eq!((123 as $T).saturating_abs(), 123);
-        assert_eq!((-123 as $T).saturating_abs(), 123);
-        assert_eq!((MAX - 2).saturating_abs(), MAX - 2);
-        assert_eq!((MAX - 1).saturating_abs(), MAX - 1);
-        assert_eq!(MAX.saturating_abs(), MAX);
-        assert_eq!((MIN + 2).saturating_abs(), MAX - 1);
-        assert_eq!((MIN + 1).saturating_abs(), MAX);
-        assert_eq!(MIN.saturating_abs(), MAX);
-    }
+            #[test]
+            fn test_saturating_abs() {
+                assert_eq!((0 as $T).saturating_abs(), 0);
+                assert_eq!((123 as $T).saturating_abs(), 123);
+                assert_eq!((-123 as $T).saturating_abs(), 123);
+                assert_eq!((MAX - 2).saturating_abs(), MAX - 2);
+                assert_eq!((MAX - 1).saturating_abs(), MAX - 1);
+                assert_eq!(MAX.saturating_abs(), MAX);
+                assert_eq!((MIN + 2).saturating_abs(), MAX - 1);
+                assert_eq!((MIN + 1).saturating_abs(), MAX);
+                assert_eq!(MIN.saturating_abs(), MAX);
+            }
 
-    #[test]
-    fn test_saturating_neg() {
-        assert_eq!((0 as $T).saturating_neg(), 0);
-        assert_eq!((123 as $T).saturating_neg(), -123);
-        assert_eq!((-123 as $T).saturating_neg(), 123);
-        assert_eq!((MAX - 2).saturating_neg(), MIN + 3);
-        assert_eq!((MAX - 1).saturating_neg(), MIN + 2);
-        assert_eq!(MAX.saturating_neg(), MIN + 1);
-        assert_eq!((MIN + 2).saturating_neg(), MAX - 1);
-        assert_eq!((MIN + 1).saturating_neg(), MAX);
-        assert_eq!(MIN.saturating_neg(), MAX);
-    }
+            #[test]
+            fn test_saturating_neg() {
+                assert_eq!((0 as $T).saturating_neg(), 0);
+                assert_eq!((123 as $T).saturating_neg(), -123);
+                assert_eq!((-123 as $T).saturating_neg(), 123);
+                assert_eq!((MAX - 2).saturating_neg(), MIN + 3);
+                assert_eq!((MAX - 1).saturating_neg(), MIN + 2);
+                assert_eq!(MAX.saturating_neg(), MIN + 1);
+                assert_eq!((MIN + 2).saturating_neg(), MAX - 1);
+                assert_eq!((MIN + 1).saturating_neg(), MAX);
+                assert_eq!(MIN.saturating_neg(), MAX);
+            }
 
-    #[test]
-    fn test_from_str() {
-        fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
-            ::std::str::FromStr::from_str(t).ok()
+            #[test]
+            fn test_from_str() {
+                fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
+                    ::std::str::FromStr::from_str(t).ok()
+                }
+                assert_eq!(from_str::<$T>("0"), Some(0 as $T));
+                assert_eq!(from_str::<$T>("3"), Some(3 as $T));
+                assert_eq!(from_str::<$T>("10"), Some(10 as $T));
+                assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
+                assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
+
+                assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
+                assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
+                assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
+                assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
+                assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
+
+                assert_eq!(from_str::<$T>(""), None);
+                assert_eq!(from_str::<$T>(" "), None);
+                assert_eq!(from_str::<$T>("x"), None);
+            }
+
+            #[test]
+            fn test_from_str_radix() {
+                assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
+                assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
+                assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
+                assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
+                assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
+                assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
+                assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
+                assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));
+
+                assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
+                assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
+                assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
+                assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
+                assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
+                assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
+                assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
+                assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
+
+                assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
+                assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
+            }
+
+            #[test]
+            fn test_pow() {
+                let mut r = 2 as $T;
+
+                assert_eq!(r.pow(2), 4 as $T);
+                assert_eq!(r.pow(0), 1 as $T);
+                r = -2 as $T;
+                assert_eq!(r.pow(2), 4 as $T);
+                assert_eq!(r.pow(3), -8 as $T);
+            }
         }
-        assert_eq!(from_str::<$T>("0"), Some(0 as $T));
-        assert_eq!(from_str::<$T>("3"), Some(3 as $T));
-        assert_eq!(from_str::<$T>("10"), Some(10 as $T));
-        assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
-        assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
-
-        assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
-        assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
-        assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
-        assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
-        assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
-
-        assert_eq!(from_str::<$T>(""), None);
-        assert_eq!(from_str::<$T>(" "), None);
-        assert_eq!(from_str::<$T>("x"), None);
-    }
-
-    #[test]
-    fn test_from_str_radix() {
-        assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
-        assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
-        assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
-        assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
-        assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
-        assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
-        assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
-        assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));
-
-        assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
-        assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
-        assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
-        assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
-        assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
-        assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
-        assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
-        assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
-
-        assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
-        assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
-    }
-
-    #[test]
-    fn test_pow() {
-        let mut r = 2 as $T;
-
-        assert_eq!(r.pow(2), 4 as $T);
-        assert_eq!(r.pow(0), 1 as $T);
-        r = -2 as $T;
-        assert_eq!(r.pow(2), 4 as $T);
-        assert_eq!(r.pow(3), -8 as $T);
-    }
+    };
 }
-
-)}
diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs
index 04ed14f..f94b2f5 100644
--- a/src/libcore/tests/num/uint_macros.rs
+++ b/src/libcore/tests/num/uint_macros.rs
@@ -1,160 +1,162 @@
-macro_rules! uint_module { ($T:ident, $T_i:ident) => (
-#[cfg(test)]
-mod tests {
-    use core::$T_i::*;
-    use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not};
-    use std::str::FromStr;
-    use std::mem;
+macro_rules! uint_module {
+    ($T:ident, $T_i:ident) => {
+        #[cfg(test)]
+        mod tests {
+            use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
+            use core::$T_i::*;
+            use std::mem;
+            use std::str::FromStr;
 
-    use crate::num;
+            use crate::num;
 
-    #[test]
-    fn test_overflows() {
-        assert!(MAX > 0);
-        assert!(MIN <= 0);
-        assert!((MIN + MAX).wrapping_add(1) == 0);
-    }
+            #[test]
+            fn test_overflows() {
+                assert!(MAX > 0);
+                assert!(MIN <= 0);
+                assert!((MIN + MAX).wrapping_add(1) == 0);
+            }
 
-    #[test]
-    fn test_num() {
-        num::test_num(10 as $T, 2 as $T);
-    }
+            #[test]
+            fn test_num() {
+                num::test_num(10 as $T, 2 as $T);
+            }
 
-    #[test]
-    fn test_bitwise_operators() {
-        assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
-        assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
-        assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
-        assert!(0b1110 as $T == (0b0111 as $T).shl(1));
-        assert!(0b0111 as $T == (0b1110 as $T).shr(1));
-        assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not());
-    }
+            #[test]
+            fn test_bitwise_operators() {
+                assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
+                assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
+                assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
+                assert!(0b1110 as $T == (0b0111 as $T).shl(1));
+                assert!(0b0111 as $T == (0b1110 as $T).shr(1));
+                assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not());
+            }
 
-    const A: $T = 0b0101100;
-    const B: $T = 0b0100001;
-    const C: $T = 0b1111001;
+            const A: $T = 0b0101100;
+            const B: $T = 0b0100001;
+            const C: $T = 0b1111001;
 
-    const _0: $T = 0;
-    const _1: $T = !0;
+            const _0: $T = 0;
+            const _1: $T = !0;
 
-    #[test]
-    fn test_count_ones() {
-        assert!(A.count_ones() == 3);
-        assert!(B.count_ones() == 2);
-        assert!(C.count_ones() == 5);
-    }
+            #[test]
+            fn test_count_ones() {
+                assert!(A.count_ones() == 3);
+                assert!(B.count_ones() == 2);
+                assert!(C.count_ones() == 5);
+            }
 
-    #[test]
-    fn test_count_zeros() {
-        let bits = mem::size_of::<$T>() * 8;
-        assert!(A.count_zeros() == bits as u32 - 3);
-        assert!(B.count_zeros() == bits as u32 - 2);
-        assert!(C.count_zeros() == bits as u32 - 5);
-    }
+            #[test]
+            fn test_count_zeros() {
+                let bits = mem::size_of::<$T>() * 8;
+                assert!(A.count_zeros() == bits as u32 - 3);
+                assert!(B.count_zeros() == bits as u32 - 2);
+                assert!(C.count_zeros() == bits as u32 - 5);
+            }
 
-    #[test]
-    fn test_rotate() {
-        assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
-        assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
-        assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+            #[test]
+            fn test_rotate() {
+                assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+                assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+                assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
 
-        // Rotating these should make no difference
-        //
-        // We test using 124 bits because to ensure that overlong bit shifts do
-        // not cause undefined behaviour. See #10183.
-        assert_eq!(_0.rotate_left(124), _0);
-        assert_eq!(_1.rotate_left(124), _1);
-        assert_eq!(_0.rotate_right(124), _0);
-        assert_eq!(_1.rotate_right(124), _1);
+                // Rotating these should make no difference
+                //
+                // We test using 124 bits because to ensure that overlong bit shifts do
+                // not cause undefined behaviour. See #10183.
+                assert_eq!(_0.rotate_left(124), _0);
+                assert_eq!(_1.rotate_left(124), _1);
+                assert_eq!(_0.rotate_right(124), _0);
+                assert_eq!(_1.rotate_right(124), _1);
 
-        // Rotating by 0 should have no effect
-        assert_eq!(A.rotate_left(0), A);
-        assert_eq!(B.rotate_left(0), B);
-        assert_eq!(C.rotate_left(0), C);
-        // Rotating by a multiple of word size should also have no effect
-        assert_eq!(A.rotate_left(64), A);
-        assert_eq!(B.rotate_left(64), B);
-        assert_eq!(C.rotate_left(64), C);
-    }
+                // Rotating by 0 should have no effect
+                assert_eq!(A.rotate_left(0), A);
+                assert_eq!(B.rotate_left(0), B);
+                assert_eq!(C.rotate_left(0), C);
+                // Rotating by a multiple of word size should also have no effect
+                assert_eq!(A.rotate_left(64), A);
+                assert_eq!(B.rotate_left(64), B);
+                assert_eq!(C.rotate_left(64), C);
+            }
 
-    #[test]
-    fn test_swap_bytes() {
-        assert_eq!(A.swap_bytes().swap_bytes(), A);
-        assert_eq!(B.swap_bytes().swap_bytes(), B);
-        assert_eq!(C.swap_bytes().swap_bytes(), C);
+            #[test]
+            fn test_swap_bytes() {
+                assert_eq!(A.swap_bytes().swap_bytes(), A);
+                assert_eq!(B.swap_bytes().swap_bytes(), B);
+                assert_eq!(C.swap_bytes().swap_bytes(), C);
 
-        // Swapping these should make no difference
-        assert_eq!(_0.swap_bytes(), _0);
-        assert_eq!(_1.swap_bytes(), _1);
-    }
+                // Swapping these should make no difference
+                assert_eq!(_0.swap_bytes(), _0);
+                assert_eq!(_1.swap_bytes(), _1);
+            }
 
-    #[test]
-    fn test_reverse_bits() {
-        assert_eq!(A.reverse_bits().reverse_bits(), A);
-        assert_eq!(B.reverse_bits().reverse_bits(), B);
-        assert_eq!(C.reverse_bits().reverse_bits(), C);
+            #[test]
+            fn test_reverse_bits() {
+                assert_eq!(A.reverse_bits().reverse_bits(), A);
+                assert_eq!(B.reverse_bits().reverse_bits(), B);
+                assert_eq!(C.reverse_bits().reverse_bits(), C);
 
-        // Swapping these should make no difference
-        assert_eq!(_0.reverse_bits(), _0);
-        assert_eq!(_1.reverse_bits(), _1);
-    }
+                // Swapping these should make no difference
+                assert_eq!(_0.reverse_bits(), _0);
+                assert_eq!(_1.reverse_bits(), _1);
+            }
 
-    #[test]
-    fn test_le() {
-        assert_eq!($T::from_le(A.to_le()), A);
-        assert_eq!($T::from_le(B.to_le()), B);
-        assert_eq!($T::from_le(C.to_le()), C);
-        assert_eq!($T::from_le(_0), _0);
-        assert_eq!($T::from_le(_1), _1);
-        assert_eq!(_0.to_le(), _0);
-        assert_eq!(_1.to_le(), _1);
-    }
+            #[test]
+            fn test_le() {
+                assert_eq!($T::from_le(A.to_le()), A);
+                assert_eq!($T::from_le(B.to_le()), B);
+                assert_eq!($T::from_le(C.to_le()), C);
+                assert_eq!($T::from_le(_0), _0);
+                assert_eq!($T::from_le(_1), _1);
+                assert_eq!(_0.to_le(), _0);
+                assert_eq!(_1.to_le(), _1);
+            }
 
-    #[test]
-    fn test_be() {
-        assert_eq!($T::from_be(A.to_be()), A);
-        assert_eq!($T::from_be(B.to_be()), B);
-        assert_eq!($T::from_be(C.to_be()), C);
-        assert_eq!($T::from_be(_0), _0);
-        assert_eq!($T::from_be(_1), _1);
-        assert_eq!(_0.to_be(), _0);
-        assert_eq!(_1.to_be(), _1);
-    }
+            #[test]
+            fn test_be() {
+                assert_eq!($T::from_be(A.to_be()), A);
+                assert_eq!($T::from_be(B.to_be()), B);
+                assert_eq!($T::from_be(C.to_be()), C);
+                assert_eq!($T::from_be(_0), _0);
+                assert_eq!($T::from_be(_1), _1);
+                assert_eq!(_0.to_be(), _0);
+                assert_eq!(_1.to_be(), _1);
+            }
 
-    #[test]
-    fn test_unsigned_checked_div() {
-        assert!((10 as $T).checked_div(2) == Some(5));
-        assert!((5 as $T).checked_div(0) == None);
-    }
+            #[test]
+            fn test_unsigned_checked_div() {
+                assert!((10 as $T).checked_div(2) == Some(5));
+                assert!((5 as $T).checked_div(0) == None);
+            }
 
-    fn from_str<T: FromStr>(t: &str) -> Option<T> {
-        FromStr::from_str(t).ok()
-    }
+            fn from_str<T: FromStr>(t: &str) -> Option<T> {
+                FromStr::from_str(t).ok()
+            }
 
-    #[test]
-    pub fn test_from_str() {
-        assert_eq!(from_str::<$T>("0"), Some(0 as $T));
-        assert_eq!(from_str::<$T>("3"), Some(3 as $T));
-        assert_eq!(from_str::<$T>("10"), Some(10 as $T));
-        assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32));
-        assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
+            #[test]
+            pub fn test_from_str() {
+                assert_eq!(from_str::<$T>("0"), Some(0 as $T));
+                assert_eq!(from_str::<$T>("3"), Some(3 as $T));
+                assert_eq!(from_str::<$T>("10"), Some(10 as $T));
+                assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32));
+                assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
 
-        assert_eq!(from_str::<$T>(""), None);
-        assert_eq!(from_str::<$T>(" "), None);
-        assert_eq!(from_str::<$T>("x"), None);
-    }
+                assert_eq!(from_str::<$T>(""), None);
+                assert_eq!(from_str::<$T>(" "), None);
+                assert_eq!(from_str::<$T>("x"), None);
+            }
 
-    #[test]
-    pub fn test_parse_bytes() {
-        assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
-        assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
-        assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
-        assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16));
-        assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16));
-        assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
+            #[test]
+            pub fn test_parse_bytes() {
+                assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
+                assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
+                assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
+                assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16));
+                assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16));
+                assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
 
-        assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
-        assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
-    }
+                assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
+                assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
+            }
+        }
+    };
 }
-)}
diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs
index 48755ae..43eb498 100644
--- a/src/libcore/tests/ops.rs
+++ b/src/libcore/tests/ops.rs
@@ -1,4 +1,4 @@
-use core::ops::{Bound, Range, RangeFull, RangeFrom, RangeTo, RangeInclusive};
+use core::ops::{Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo};
 
 // Test the Range structs without the syntactic sugar.
 
@@ -59,28 +59,27 @@
     assert_eq!(r.next(), None);
 }
 
-
 #[test]
 fn test_range_is_empty() {
     use core::f32::*;
 
-    assert!(!(0.0 .. 10.0).is_empty());
-    assert!( (-0.0 .. 0.0).is_empty());
-    assert!( (10.0 .. 0.0).is_empty());
+    assert!(!(0.0..10.0).is_empty());
+    assert!((-0.0..0.0).is_empty());
+    assert!((10.0..0.0).is_empty());
 
-    assert!(!(NEG_INFINITY .. INFINITY).is_empty());
-    assert!( (EPSILON .. NAN).is_empty());
-    assert!( (NAN .. EPSILON).is_empty());
-    assert!( (NAN .. NAN).is_empty());
+    assert!(!(NEG_INFINITY..INFINITY).is_empty());
+    assert!((EPSILON..NAN).is_empty());
+    assert!((NAN..EPSILON).is_empty());
+    assert!((NAN..NAN).is_empty());
 
-    assert!(!(0.0 ..= 10.0).is_empty());
-    assert!(!(-0.0 ..= 0.0).is_empty());
-    assert!( (10.0 ..= 0.0).is_empty());
+    assert!(!(0.0..=10.0).is_empty());
+    assert!(!(-0.0..=0.0).is_empty());
+    assert!((10.0..=0.0).is_empty());
 
-    assert!(!(NEG_INFINITY ..= INFINITY).is_empty());
-    assert!( (EPSILON ..= NAN).is_empty());
-    assert!( (NAN ..= EPSILON).is_empty());
-    assert!( (NAN ..= NAN).is_empty());
+    assert!(!(NEG_INFINITY..=INFINITY).is_empty());
+    assert!((EPSILON..=NAN).is_empty());
+    assert!((NAN..=EPSILON).is_empty());
+    assert!((NAN..=NAN).is_empty());
 }
 
 #[test]
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
index ff43fc4..fa30816 100644
--- a/src/libcore/tests/option.rs
+++ b/src/libcore/tests/option.rs
@@ -1,8 +1,8 @@
-use core::option::*;
-use core::mem;
-use core::clone::Clone;
 use core::array::FixedSizeArray;
+use core::clone::Clone;
+use core::mem;
 use core::ops::DerefMut;
+use core::option::*;
 
 #[test]
 fn test_get_ptr() {
@@ -28,15 +28,15 @@
 
 #[test]
 fn test_get_resource() {
-    use std::rc::Rc;
     use core::cell::RefCell;
+    use std::rc::Rc;
 
     struct R {
-       i: Rc<RefCell<isize>>,
+        i: Rc<RefCell<isize>>,
     }
 
-        impl Drop for R {
-       fn drop(&mut self) {
+    impl Drop for R {
+        fn drop(&mut self) {
             let ii = &*self.i;
             let i = *ii.borrow();
             *ii.borrow_mut() = i + 1;
@@ -44,9 +44,7 @@
     }
 
     fn r(i: Rc<RefCell<isize>>) -> R {
-        R {
-            i,
-        }
+        R { i }
     }
 
     let i = Rc::new(RefCell::new(0));
@@ -70,7 +68,8 @@
     assert!(y.is_none());
 }
 
-#[test] #[should_panic]
+#[test]
+#[should_panic]
 fn test_option_too_much_dance() {
     struct A;
     let mut y = Some(A);
@@ -210,7 +209,7 @@
 fn test_ord() {
     let small = Some(1.0f64);
     let big = Some(5.0f64);
-    let nan = Some(0.0f64/0.0);
+    let nan = Some(0.0f64 / 0.0);
     assert!(!(nan < big));
     assert!(!(nan > big));
     assert!(small < big);
@@ -226,9 +225,7 @@
     let v: Option<Vec<isize>> = (0..3).map(|x| Some(x)).collect();
     assert!(v == Some(vec![0, 1, 2]));
 
-    let v: Option<Vec<isize>> = (0..3).map(|x| {
-        if x > 1 { None } else { Some(x) }
-    }).collect();
+    let v: Option<Vec<isize>> = (0..3).map(|x| if x > 1 { None } else { Some(x) }).collect();
     assert!(v == None);
 
     // test that it does not take more elements than it needs
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
index 1a6be3a..eea736b 100644
--- a/src/libcore/tests/ptr.rs
+++ b/src/libcore/tests/ptr.rs
@@ -1,14 +1,14 @@
-use core::ptr::*;
 use core::cell::RefCell;
+use core::ptr::*;
 
 #[test]
 fn test() {
     unsafe {
         struct Pair {
             fst: isize,
-            snd: isize
+            snd: isize,
         };
-        let mut p = Pair {fst: 10, snd: 20};
+        let mut p = Pair { fst: 10, snd: 20 };
         let pptr: *mut Pair = &mut p;
         let iptr: *mut isize = pptr as *mut isize;
         assert_eq!(*iptr, 10);
@@ -16,7 +16,7 @@
         assert_eq!(*iptr, 30);
         assert_eq!(p.fst, 30);
 
-        *pptr = Pair {fst: 50, snd: 60};
+        *pptr = Pair { fst: 50, snd: 60 };
         assert_eq!(*iptr, 50);
         assert_eq!(p.fst, 50);
         assert_eq!(p.snd, 60);
@@ -25,17 +25,11 @@
         let mut v1 = vec![0u16, 0u16, 0u16];
 
         copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
-        assert!((v1[0] == 0u16 &&
-                 v1[1] == 32001u16 &&
-                 v1[2] == 0u16));
+        assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16));
         copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
-        assert!((v1[0] == 32002u16 &&
-                 v1[1] == 32001u16 &&
-                 v1[2] == 0u16));
+        assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16));
         copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
-        assert!((v1[0] == 32002u16 &&
-                 v1[1] == 32001u16 &&
-                 v1[2] == 32000u16));
+        assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16));
     }
 }
 
@@ -208,7 +202,7 @@
 #[test]
 fn test_ptr_subtraction() {
     unsafe {
-        let xs = vec![0,1,2,3,4,5,6,7,8,9];
+        let xs = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
         let mut idx = 9;
         let ptr = xs.as_ptr();
 
@@ -229,7 +223,7 @@
             m_ptr = m_ptr.offset(-1);
         }
 
-        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
+        assert_eq!(xs_mut, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
     }
 }
 
@@ -237,7 +231,9 @@
 fn test_set_memory() {
     let mut xs = [0u8; 20];
     let ptr = xs.as_mut_ptr();
-    unsafe { write_bytes(ptr, 5u8, xs.len()); }
+    unsafe {
+        write_bytes(ptr, 5u8, xs.len());
+    }
     assert!(xs == [5u8; 20]);
 }
 
@@ -257,10 +253,10 @@
 #[no_mangle]
 pub fn test_variadic_fnptr() {
     use core::hash::{Hash, SipHasher};
-    extern {
+    extern "C" {
         fn test_variadic_fnptr(_: u64, ...) -> f64;
     }
-    let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
+    let p: unsafe extern "C" fn(u64, ...) -> f64 = test_variadic_fnptr;
     let q = p.clone();
     assert_eq!(p, q);
     assert!(!(p < q));
@@ -285,13 +281,15 @@
     {
         let c = Dropper(0);
         let mut t = Dropper(1);
-        unsafe { write_unaligned(&mut t, c); }
+        unsafe {
+            write_unaligned(&mut t, c);
+        }
     }
     DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
+#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset`
 fn align_offset_zst() {
     // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
     // all, because no amount of elements will align the pointer.
@@ -306,24 +304,29 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
+#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset`
 fn align_offset_stride1() {
     // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
     // number of bytes.
     let mut align = 1;
     while align < 1024 {
-        for ptr in 1..2*align {
+        for ptr in 1..2 * align {
             let expected = ptr % align;
             let offset = if expected == 0 { 0 } else { align - expected };
-            assert_eq!((ptr as *const u8).align_offset(align), offset,
-            "ptr = {}, align = {}, size = 1", ptr, align);
+            assert_eq!(
+                (ptr as *const u8).align_offset(align),
+                offset,
+                "ptr = {}, align = {}, size = 1",
+                ptr,
+                align
+            );
         }
         align = (align + 1).next_power_of_two();
     }
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn align_offset_weird_strides() {
     #[repr(packed)]
     struct A3(u16, u8);
@@ -353,8 +356,14 @@
         }
         let got = ptr.align_offset(align);
         if got != expected {
-            eprintln!("aligning {:p} (with stride of {}) to {}, expected {}, got {}", ptr,
-                      ::std::mem::size_of::<T>(), align, expected, got);
+            eprintln!(
+                "aligning {:p} (with stride of {}) to {}, expected {}, got {}",
+                ptr,
+                ::std::mem::size_of::<T>(),
+                align,
+                expected,
+                got
+            );
             return true;
         }
         return false;
@@ -365,7 +374,7 @@
     let mut align = 1;
     let mut x = false;
     while align < 1024 {
-        for ptr in 1usize..4*align {
+        for ptr in 1usize..4 * align {
             unsafe {
                 x |= test_weird_stride::<A3>(ptr as *const A3, align);
                 x |= test_weird_stride::<A4>(ptr as *const A4, align);
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 6609bc3..cc274b4 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -1,4 +1,4 @@
-use core::result::Result::{Ok, Err};
+use core::result::Result::{Err, Ok};
 
 #[test]
 fn test_position() {
@@ -50,8 +50,14 @@
     assert_eq!(b.binary_search(&0), Err(0));
     assert_eq!(b.binary_search(&1), Ok(0));
     assert_eq!(b.binary_search(&2), Err(1));
-    assert!(match b.binary_search(&3) { Ok(1..=3) => true, _ => false });
-    assert!(match b.binary_search(&3) { Ok(1..=3) => true, _ => false });
+    assert!(match b.binary_search(&3) {
+        Ok(1..=3) => true,
+        _ => false,
+    });
+    assert!(match b.binary_search(&3) {
+        Ok(1..=3) => true,
+        _ => false,
+    });
     assert_eq!(b.binary_search(&4), Err(4));
     assert_eq!(b.binary_search(&5), Err(4));
     assert_eq!(b.binary_search(&6), Err(4));
@@ -187,7 +193,8 @@
     let v1: &[i32] = &[0, 1, 2, 3, 4];
     let v2: &[i32] = &[6, 7, 8, 9, 10];
 
-    let res = v1.chunks(2)
+    let res = v1
+        .chunks(2)
         .zip(v2.chunks(2))
         .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
         .collect::<Vec<_>>();
@@ -339,7 +346,8 @@
     let v1: &[i32] = &[0, 1, 2, 3, 4];
     let v2: &[i32] = &[6, 7, 8, 9, 10];
 
-    let res = v1.chunks_exact(2)
+    let res = v1
+        .chunks_exact(2)
         .zip(v2.chunks_exact(2))
         .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
         .collect::<Vec<_>>();
@@ -482,7 +490,8 @@
     let v1: &[i32] = &[0, 1, 2, 3, 4];
     let v2: &[i32] = &[6, 7, 8, 9, 10];
 
-    let res = v1.rchunks(2)
+    let res = v1
+        .rchunks(2)
         .zip(v2.rchunks(2))
         .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
         .collect::<Vec<_>>();
@@ -619,7 +628,8 @@
     let v1: &[i32] = &[0, 1, 2, 3, 4];
     let v2: &[i32] = &[6, 7, 8, 9, 10];
 
-    let res = v1.rchunks_exact(2)
+    let res = v1
+        .rchunks_exact(2)
         .zip(v2.rchunks_exact(2))
         .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
         .collect::<Vec<_>>();
@@ -756,7 +766,8 @@
     let v1: &[i32] = &[0, 1, 2, 3, 4];
     let v2: &[i32] = &[6, 7, 8, 9, 10];
 
-    let res = v1.windows(2)
+    let res = v1
+        .windows(2)
         .zip(v2.windows(2))
         .map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
         .collect::<Vec<_>>();
@@ -769,11 +780,11 @@
 fn test_iter_ref_consistency() {
     use std::fmt::Debug;
 
-    fn test<T : Copy + Debug + PartialEq>(x : T) {
-        let v : &[T] = &[x, x, x];
-        let v_ptrs : [*const T; 3] = match v {
+    fn test<T: Copy + Debug + PartialEq>(x: T) {
+        let v: &[T] = &[x, x, x];
+        let v_ptrs: [*const T; 3] = match v {
             [ref v1, ref v2, ref v3] => [v1 as *const _, v2 as *const _, v3 as *const _],
-            _ => unreachable!()
+            _ => unreachable!(),
         };
         let len = v.len();
 
@@ -817,19 +828,20 @@
                 assert_eq!(it.size_hint(), (remaining, Some(remaining)));
 
                 let prev = it.next_back().unwrap();
-                assert_eq!(prev as *const _, v_ptrs[remaining-1]);
+                assert_eq!(prev as *const _, v_ptrs[remaining - 1]);
             }
             assert_eq!(it.size_hint(), (0, Some(0)));
             assert_eq!(it.next_back(), None, "The final call to next_back() should return None");
         }
     }
 
-    fn test_mut<T : Copy + Debug + PartialEq>(x : T) {
-        let v : &mut [T] = &mut [x, x, x];
-        let v_ptrs : [*mut T; 3] = match v {
-            [ref v1, ref v2, ref v3] =>
-              [v1 as *const _ as *mut _, v2 as *const _ as *mut _, v3 as *const _ as *mut _],
-            _ => unreachable!()
+    fn test_mut<T: Copy + Debug + PartialEq>(x: T) {
+        let v: &mut [T] = &mut [x, x, x];
+        let v_ptrs: [*mut T; 3] = match v {
+            [ref v1, ref v2, ref v3] => {
+                [v1 as *const _ as *mut _, v2 as *const _ as *mut _, v3 as *const _ as *mut _]
+            }
+            _ => unreachable!(),
         };
         let len = v.len();
 
@@ -873,7 +885,7 @@
                 assert_eq!(it.size_hint(), (remaining, Some(remaining)));
 
                 let prev = it.next_back().unwrap();
-                assert_eq!(prev as *mut _, v_ptrs[remaining-1]);
+                assert_eq!(prev as *mut _, v_ptrs[remaining - 1]);
             }
             assert_eq!(it.size_hint(), (0, Some(0)));
             assert_eq!(it.next_back(), None, "The final call to next_back() should return None");
@@ -897,8 +909,7 @@
     // This checks all six indexing methods, given an input range that
     // should succeed. (it is NOT suitable for testing invalid inputs)
     macro_rules! assert_range_eq {
-        ($arr:expr, $range:expr, $expected:expr)
-        => {
+        ($arr:expr, $range:expr, $expected:expr) => {
             let mut arr = $arr;
             let mut expected = $expected;
             {
@@ -909,7 +920,8 @@
                 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
                 unsafe {
                     assert_eq!(
-                        s.get_unchecked($range), expected,
+                        s.get_unchecked($range),
+                        expected,
                         "(in assertion for: get_unchecked)",
                     );
                 }
@@ -918,22 +930,21 @@
                 let s: &mut [_] = &mut arr;
                 let expected: &mut [_] = &mut expected;
 
+                assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",);
                 assert_eq!(
-                    &mut s[$range], expected,
-                    "(in assertion for: index_mut)",
-                );
-                assert_eq!(
-                    s.get_mut($range), Some(&mut expected[..]),
+                    s.get_mut($range),
+                    Some(&mut expected[..]),
                     "(in assertion for: get_mut)",
                 );
                 unsafe {
                     assert_eq!(
-                        s.get_unchecked_mut($range), expected,
+                        s.get_unchecked_mut($range),
+                        expected,
                         "(in assertion for: get_unchecked_mut)",
                     );
                 }
             }
-        }
+        };
     }
 
     // Make sure the macro can actually detect bugs,
@@ -1126,8 +1137,8 @@
 #[test]
 fn test_iter_folds() {
     let a = [1, 2, 3, 4, 5]; // len>4 so the unroll is used
-    assert_eq!(a.iter().fold(0, |acc, &x| 2*acc + x), 57);
-    assert_eq!(a.iter().rfold(0, |acc, &x| 2*acc + x), 129);
+    assert_eq!(a.iter().fold(0, |acc, &x| 2 * acc + x), 57);
+    assert_eq!(a.iter().rfold(0, |acc, &x| 2 * acc + x), 129);
     let fold = |acc: i32, &x| acc.checked_mul(2)?.checked_add(x);
     assert_eq!(a.iter().try_fold(0, &fold), Some(57));
     assert_eq!(a.iter().try_rfold(0, &fold), Some(129));
@@ -1172,7 +1183,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn brute_force_rotate_test_0() {
     // In case of edge cases involving multiple algorithms
     let n = 300;
@@ -1214,7 +1225,7 @@
 fn sort_unstable() {
     use core::cmp::Ordering::{Equal, Greater, Less};
     use core::slice::heapsort;
-    use rand::{SeedableRng, Rng, rngs::StdRng, seq::SliceRandom};
+    use rand::{rngs::StdRng, seq::SliceRandom, Rng, SeedableRng};
 
     #[cfg(not(miri))] // Miri is too slow
     let large_range = 500..510;
@@ -1291,12 +1302,12 @@
 
 #[test]
 #[cfg(not(target_arch = "wasm32"))]
-#[cfg(not(miri))] // Miri is too slow
+#[cfg_attr(miri, ignore)] // Miri is too slow
 fn partition_at_index() {
     use core::cmp::Ordering::{Equal, Greater, Less};
     use rand::rngs::StdRng;
     use rand::seq::SliceRandom;
-    use rand::{SeedableRng, Rng};
+    use rand::{Rng, SeedableRng};
 
     let mut rng = StdRng::from_entropy();
 
@@ -1494,7 +1505,7 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
+#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset`
 fn test_align_to_simple() {
     let bytes = [1u8, 2, 3, 4, 5, 6, 7];
     let (prefix, aligned, suffix) = unsafe { bytes.align_to::<u16>() };
@@ -1504,9 +1515,15 @@
     let expect2 = [1 | 2 << 8, 3 | 4 << 8, 5 | 6 << 8];
     let expect3 = [2 << 8 | 3, 4 << 8 | 5, 6 << 8 | 7];
     let expect4 = [2 | 3 << 8, 4 | 5 << 8, 6 | 7 << 8];
-    assert!(aligned == expect1 || aligned == expect2 || aligned == expect3 || aligned == expect4,
-            "aligned={:?} expected={:?} || {:?} || {:?} || {:?}",
-            aligned, expect1, expect2, expect3, expect4);
+    assert!(
+        aligned == expect1 || aligned == expect2 || aligned == expect3 || aligned == expect4,
+        "aligned={:?} expected={:?} || {:?} || {:?} || {:?}",
+        aligned,
+        expect1,
+        expect2,
+        expect3,
+        expect4
+    );
 }
 
 #[test]
@@ -1518,12 +1535,22 @@
 }
 
 #[test]
-#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
+#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset`
 fn test_align_to_non_trivial() {
-    #[repr(align(8))] struct U64(u64, u64);
-    #[repr(align(8))] struct U64U64U32(u64, u64, u32);
-    let data = [U64(1, 2), U64(3, 4), U64(5, 6), U64(7, 8), U64(9, 10), U64(11, 12), U64(13, 14),
-                U64(15, 16)];
+    #[repr(align(8))]
+    struct U64(u64, u64);
+    #[repr(align(8))]
+    struct U64U64U32(u64, u64, u32);
+    let data = [
+        U64(1, 2),
+        U64(3, 4),
+        U64(5, 6),
+        U64(7, 8),
+        U64(9, 10),
+        U64(11, 12),
+        U64(13, 14),
+        U64(15, 16),
+    ];
     let (prefix, aligned, suffix) = unsafe { data.align_to::<U64U64U32>() };
     assert_eq!(aligned.len(), 4);
     assert_eq!(prefix.len() + suffix.len(), 2);
@@ -1538,7 +1565,7 @@
     let bytes = [1, 2, 3, 4, 5, 6, 7];
     type Chunk = u32;
     for offset in 0..4 {
-        let (_, mid, _) = unsafe { bytes[offset..offset+1].align_to::<Chunk>() };
+        let (_, mid, _) = unsafe { bytes[offset..offset + 1].align_to::<Chunk>() };
         assert_eq!(mid.as_ptr() as usize % mem::align_of::<Chunk>(), 0);
     }
 }
diff --git a/src/libcore/tests/str_lossy.rs b/src/libcore/tests/str_lossy.rs
index f9fd333..d4b47a4 100644
--- a/src/libcore/tests/str_lossy.rs
+++ b/src/libcore/tests/str_lossy.rs
@@ -3,65 +3,65 @@
 #[test]
 fn chunks() {
     let mut iter = Utf8Lossy::from_bytes(b"hello").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "hello", broken: b"", }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "hello", broken: b"" }), iter.next());
     assert_eq!(None, iter.next());
 
     let mut iter = Utf8Lossy::from_bytes("ศไทย中华Việt Nam".as_bytes()).chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "ศไทย中华Việt Nam", broken: b"", }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "ศไทย中华Việt Nam", broken: b"" }), iter.next());
     assert_eq!(None, iter.next());
 
     let mut iter = Utf8Lossy::from_bytes(b"Hello\xC2 There\xFF Goodbye").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC2", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xFF", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC2" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xFF" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"" }), iter.next());
     assert_eq!(None, iter.next());
 
     let mut iter = Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC0", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xE6\x83", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC0" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xE6\x83" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"" }), iter.next());
     assert_eq!(None, iter.next());
 
     let mut iter = Utf8Lossy::from_bytes(b"\xF5foo\xF5\x80bar").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF5", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF5", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF5" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF5" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"" }), iter.next());
     assert_eq!(None, iter.next());
 
     let mut iter = Utf8Lossy::from_bytes(b"\xF1foo\xF1\x80bar\xF1\x80\x80baz").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF1", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF1\x80", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF1\x80\x80", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF1" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF1\x80" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF1\x80\x80" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"" }), iter.next());
     assert_eq!(None, iter.next());
 
     let mut iter = Utf8Lossy::from_bytes(b"\xF4foo\xF4\x80bar\xF4\xBFbaz").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF4", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF4\x80", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF4", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF4" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF4\x80" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF4" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"" }), iter.next());
     assert_eq!(None, iter.next());
 
     let mut iter = Utf8Lossy::from_bytes(b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF0", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo\u{10000}bar", broken: b"", }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF0" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "foo\u{10000}bar", broken: b"" }), iter.next());
     assert_eq!(None, iter.next());
 
     // surrogates
     let mut iter = Utf8Lossy::from_bytes(b"\xED\xA0\x80foo\xED\xBF\xBFbar").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xED", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xA0", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xED", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xED" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xA0" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xED" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF" }), iter.next());
+    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"" }), iter.next());
     assert_eq!(None, iter.next());
 }
 
@@ -69,13 +69,17 @@
 fn display() {
     assert_eq!(
         "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye",
-        &Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string());
+        &Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string()
+    );
 }
 
 #[test]
 fn debug() {
     assert_eq!(
         "\"Hello\\xc0\\x80 There\\xe6\\x83 Goodbye\\u{10d4ea}\"",
-        &format!("{:?}", Utf8Lossy::from_bytes(
-            b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa")));
+        &format!(
+            "{:?}",
+            Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa")
+        )
+    );
 }
diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs
index fac70c4..273f125 100644
--- a/src/libcore/tests/time.rs
+++ b/src/libcore/tests/time.rs
@@ -3,10 +3,11 @@
 #[test]
 fn creation() {
     assert_ne!(Duration::from_secs(1), Duration::from_secs(0));
-    assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
-               Duration::from_secs(3));
-    assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
-               Duration::new(4, 10 * 1_000_000));
+    assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), Duration::from_secs(3));
+    assert_eq!(
+        Duration::from_millis(10) + Duration::from_secs(4),
+        Duration::new(4, 10 * 1_000_000)
+    );
     assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
 }
 
@@ -68,29 +69,25 @@
 
 #[test]
 fn add() {
-    assert_eq!(Duration::new(0, 0) + Duration::new(0, 1),
-               Duration::new(0, 1));
-    assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001),
-               Duration::new(1, 1));
+    assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), Duration::new(0, 1));
+    assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), Duration::new(1, 1));
 }
 
 #[test]
 fn checked_add() {
-    assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)),
-               Some(Duration::new(0, 1)));
-    assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)),
-               Some(Duration::new(1, 1)));
+    assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
+    assert_eq!(
+        Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)),
+        Some(Duration::new(1, 1))
+    );
     assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::core::u64::MAX, 0)), None);
 }
 
 #[test]
 fn sub() {
-    assert_eq!(Duration::new(0, 1) - Duration::new(0, 0),
-               Duration::new(0, 1));
-    assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000),
-               Duration::new(0, 1));
-    assert_eq!(Duration::new(1, 0) - Duration::new(0, 1),
-               Duration::new(0, 999_999_999));
+    assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), Duration::new(0, 1));
+    assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), Duration::new(0, 1));
+    assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), Duration::new(0, 999_999_999));
 }
 
 #[test]
@@ -99,8 +96,7 @@
     let one_nano = Duration::new(0, 1);
     let one_sec = Duration::new(1, 0);
     assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1)));
-    assert_eq!(one_sec.checked_sub(one_nano),
-               Some(Duration::new(0, 999_999_999)));
+    assert_eq!(one_sec.checked_sub(one_nano), Some(Duration::new(0, 999_999_999)));
     assert_eq!(zero.checked_sub(one_nano), None);
     assert_eq!(zero.checked_sub(one_sec), None);
 }
@@ -122,8 +118,7 @@
     assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2));
     assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3));
     assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
-    assert_eq!(Duration::new(0, 500_000_001) * 4000,
-               Duration::new(2000, 4000));
+    assert_eq!(Duration::new(0, 500_000_001) * 4000, Duration::new(2000, 4000));
 }
 
 #[test]
@@ -131,8 +126,7 @@
     assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2)));
     assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3)));
     assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4)));
-    assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000),
-               Some(Duration::new(2000, 4000)));
+    assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), Some(Duration::new(2000, 4000)));
     assert_eq!(Duration::new(::core::u64::MAX - 1, 0).checked_mul(2), None);
 }
 
@@ -140,8 +134,7 @@
 fn div() {
     assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
     assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
-    assert_eq!(Duration::new(99, 999_999_000) / 100,
-               Duration::new(0, 999_999_990));
+    assert_eq!(Duration::new(99, 999_999_000) / 100, Duration::new(0, 999_999_990));
 }
 
 #[test]
@@ -162,7 +155,7 @@
         Duration::new(5, 0),
     ];
     let sum = durations.iter().sum::<Duration>();
-    assert_eq!(sum, Duration::new(1+2+5+4, 1_000_000_000 - 5));
+    assert_eq!(sum, Duration::new(1 + 2 + 5 + 4, 1_000_000_000 - 5));
 }
 
 #[test]
@@ -286,9 +279,9 @@
 
 #[test]
 fn debug_formatting_precision_high() {
-    assert_eq!(format!("{:.5?}",  Duration::new(0, 23_678)), "23.67800µs");
+    assert_eq!(format!("{:.5?}", Duration::new(0, 23_678)), "23.67800µs");
 
-    assert_eq!(format!("{:.9?}",  Duration::new(1, 000_000_000)), "1.000000000s");
+    assert_eq!(format!("{:.9?}", Duration::new(1, 000_000_000)), "1.000000000s");
     assert_eq!(format!("{:.10?}", Duration::new(4, 001_000_000)), "4.0010000000s");
     assert_eq!(format!("{:.20?}", Duration::new(4, 001_000_000)), "4.00100000000000000000s");
 }
diff --git a/src/libcore/tests/tuple.rs b/src/libcore/tests/tuple.rs
index c7ed161..3a29146 100644
--- a/src/libcore/tests/tuple.rs
+++ b/src/libcore/tests/tuple.rs
@@ -1,4 +1,4 @@
-use std::cmp::Ordering::{Equal, Less, Greater};
+use std::cmp::Ordering::{Equal, Greater, Less};
 use std::f64::NAN;
 
 #[test]
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 900c6ed..2ecbe77 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -11,6 +11,7 @@
 #![feature(nll)]
 #![feature(rustc_private)]
 #![feature(unicode_internals)]
+#![feature(bool_to_option)]
 
 pub use Piece::*;
 pub use Position::*;
@@ -644,11 +645,7 @@
                 break;
             }
         }
-        if found {
-            Some(cur)
-        } else {
-            None
-        }
+        found.then_some(cur)
     }
 }
 
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index f8ad6f8..a4536bb 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -20,7 +20,7 @@
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
 rustc-rayon = "0.3.0"
 rustc-rayon-core = "0.3.0"
-polonius-engine  = "0.10.0"
+polonius-engine = "0.11.0"
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_target = { path = "../librustc_target" }
@@ -37,6 +37,6 @@
 chalk-engine = { version = "0.9.0", default-features=false }
 rustc_fs_util = { path = "../librustc_fs_util" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
-measureme = "0.4"
+measureme = "0.5"
 rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index 364a35f..eb7a170 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -23,17 +23,17 @@
             [] generics: rustc::ty::Generics,
             [] trait_def: rustc::ty::TraitDef,
             [] adt_def: rustc::ty::AdtDef,
-            [] steal_mir: rustc::ty::steal::Steal<rustc::mir::BodyCache<$tcx>>,
-            [] mir: rustc::mir::BodyCache<$tcx>,
+            [] steal_mir: rustc::ty::steal::Steal<rustc::mir::BodyAndCache<$tcx>>,
+            [] mir: rustc::mir::BodyAndCache<$tcx>,
             [] steal_promoted: rustc::ty::steal::Steal<
                 rustc_index::vec::IndexVec<
                     rustc::mir::Promoted,
-                    rustc::mir::BodyCache<$tcx>
+                    rustc::mir::BodyAndCache<$tcx>
                 >
             >,
             [] promoted: rustc_index::vec::IndexVec<
                 rustc::mir::Promoted,
-                rustc::mir::BodyCache<$tcx>
+                rustc::mir::BodyAndCache<$tcx>
             >,
             [] tables: rustc::ty::TypeckTables<$tcx>,
             [] const_allocs: rustc::mir::interpret::Allocation,
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 0104507..d952bf7 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -710,14 +710,25 @@
                                 return None
                             }
                             None => {
-                                if !tcx.sess.has_errors() {
+                                if !tcx.sess.has_errors_or_delayed_span_bugs() {
                                     bug!("try_mark_previous_green() - Forcing the DepNode \
                                           should have set its color")
                                 } else {
-                                    // If the query we just forced has resulted
-                                    // in some kind of compilation error, we
-                                    // don't expect that the corresponding
-                                    // dep-node color has been updated.
+                                    // If the query we just forced has resulted in
+                                    // some kind of compilation error, we cannot rely on
+                                    // the dep-node color having been properly updated.
+                                    // This means that the query system has reached an
+                                    // invalid state. We let the compiler continue (by
+                                    // returning `None`) so it can emit error messages
+                                    // and wind down, but rely on the fact that this
+                                    // invalid state will not be persisted to the
+                                    // incremental compilation cache because of
+                                    // compilation errors being present.
+                                    debug!("try_mark_previous_green({:?}) - END - \
+                                            dependency {:?} resulted in compilation error",
+                                           dep_node,
+                                           dep_dep_node);
+                                    return None
                                 }
                             }
                         }
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index f25f3b5..8f9f398 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -147,13 +147,7 @@
             map::Node::Expr(e) => e.is_fn_like(),
             _ => false
         };
-        if fn_like {
-            Some(FnLikeNode {
-                node,
-            })
-        } else {
-            None
-        }
+        fn_like.then_some(FnLikeNode { node })
     }
 
     pub fn body(self) -> ast::BodyId {
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 5a940f2..c9d5770 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -70,6 +70,7 @@
 mod note;
 
 mod need_type_info;
+pub use need_type_info::TypeAnnotationNeeded;
 
 pub mod nice_region_error;
 
@@ -1809,12 +1810,17 @@
                             sub_region,
                             "...",
                         );
-                        err.note(&format!(
-                            "...so that the {}:\nexpected {}\n   found {}",
-                            sup_trace.cause.as_requirement_str(),
-                            sup_expected.content(),
-                            sup_found.content()
+                        err.span_note(sup_trace.cause.span, &format!(
+                            "...so that the {}",
+                            sup_trace.cause.as_requirement_str()
                         ));
+
+                        err.note_expected_found(
+                            &"",
+                            sup_expected,
+                            &"",
+                            sup_found
+                        );
                         err.emit();
                         return;
                     }
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 32eecdf..8878683 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -1,4 +1,4 @@
-use crate::hir::def::Namespace;
+use crate::hir::def::{DefKind, Namespace};
 use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat};
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use crate::infer::InferCtxt;
@@ -6,8 +6,10 @@
 use crate::ty::{self, Ty, Infer, TyVar};
 use crate::ty::print::Print;
 use syntax::source_map::DesugaringKind;
+use syntax::symbol::kw;
 use syntax_pos::Span;
 use errors::{Applicability, DiagnosticBuilder};
+use std::borrow::Cow;
 
 use rustc_error_codes::*;
 
@@ -19,6 +21,7 @@
     found_arg_pattern: Option<&'tcx Pat>,
     found_ty: Option<Ty<'tcx>>,
     found_closure: Option<&'tcx ExprKind>,
+    found_method_call: Option<&'tcx Expr>,
 }
 
 impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
@@ -35,6 +38,7 @@
             found_arg_pattern: None,
             found_ty: None,
             found_closure: None,
+            found_method_call: None,
         }
     }
 
@@ -93,11 +97,12 @@
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr) {
-        if let (ExprKind::Closure(_, _fn_decl, _id, _sp, _), Some(_)) = (
-            &expr.kind,
-            self.node_matches_type(expr.hir_id),
-        ) {
-            self.found_closure = Some(&expr.kind);
+        if self.node_matches_type(expr.hir_id).is_some() {
+            match expr.kind {
+                ExprKind::Closure(..) => self.found_closure = Some(&expr.kind),
+                ExprKind::MethodCall(..) => self.found_method_call = Some(&expr),
+                _ => {}
+            }
         }
         intravisit::walk_expr(self, expr);
     }
@@ -109,6 +114,7 @@
     err: &mut DiagnosticBuilder<'_>,
     output: &FunctionRetTy,
     body: &Body,
+    descr: &str,
     name: &str,
     ret: &str,
 ) {
@@ -132,7 +138,7 @@
         suggestion,
         Applicability::HasPlaceholders,
     );
-    err.span_label(span, InferCtxt::missing_type_msg(&name));
+    err.span_label(span, InferCtxt::missing_type_msg(&name, &descr));
 }
 
 /// Given a closure signature, return a `String` containing a list of all its argument types.
@@ -147,17 +153,42 @@
         .unwrap_or_default()
 }
 
+pub enum TypeAnnotationNeeded {
+    E0282,
+    E0283,
+    E0284,
+}
+
+impl Into<errors::DiagnosticId> for TypeAnnotationNeeded {
+    fn into(self) -> errors::DiagnosticId {
+        syntax::diagnostic_used!(E0282);
+        syntax::diagnostic_used!(E0283);
+        syntax::diagnostic_used!(E0284);
+        errors::DiagnosticId::Error(match self {
+            Self::E0282 => "E0282".to_string(),
+            Self::E0283 => "E0283".to_string(),
+            Self::E0284 => "E0284".to_string(),
+        })
+    }
+}
+
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn extract_type_name(
         &self,
         ty: Ty<'tcx>,
         highlight: Option<ty::print::RegionHighlightMode>,
-    ) -> (String, Option<Span>) {
+    ) -> (String, Option<Span>, Cow<'static, str>) {
         if let ty::Infer(ty::TyVar(ty_vid)) = ty.kind {
             let ty_vars = self.type_variables.borrow();
             let var_origin = ty_vars.var_origin(ty_vid);
             if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind {
-                return (name.to_string(), Some(var_origin.span));
+                if name != kw::SelfUpper {
+                    return (
+                        name.to_string(),
+                        Some(var_origin.span),
+                        "type parameter".into(),
+                    );
+                }
             }
         }
 
@@ -167,7 +198,7 @@
             printer.region_highlight_mode = highlight;
         }
         let _ = ty.print(printer);
-        (s, None)
+        (s, None, ty.prefix_string())
     }
 
     pub fn need_type_info_err(
@@ -175,9 +206,10 @@
         body_id: Option<hir::BodyId>,
         span: Span,
         ty: Ty<'tcx>,
+        error_code: TypeAnnotationNeeded,
     ) -> DiagnosticBuilder<'tcx> {
         let ty = self.resolve_vars_if_possible(&ty);
-        let (name, name_sp) = self.extract_type_name(&ty, None);
+        let (name, name_sp, descr) = self.extract_type_name(&ty, None);
 
         let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir());
         let ty_to_string = |ty: Ty<'tcx>| -> String {
@@ -185,8 +217,8 @@
             let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
             let ty_vars = self.type_variables.borrow();
             let getter = move |ty_vid| {
-                if let TypeVariableOriginKind::TypeParameterDefinition(name) =
-                    ty_vars.var_origin(ty_vid).kind {
+                let var_origin = ty_vars.var_origin(ty_vid);
+                if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind {
                     return Some(name.to_string());
                 }
                 None
@@ -210,6 +242,22 @@
             // 3 |     let _ = x.sum() as f64;
             //   |               ^^^ cannot infer type for `S`
             span
+        } else if let Some(
+            ExprKind::MethodCall(_, call_span, _),
+        ) = local_visitor.found_method_call.map(|e| &e.kind) {
+            // Point at the call instead of the whole expression:
+            // error[E0284]: type annotations needed
+            //  --> file.rs:2:5
+            //   |
+            // 2 |     vec![Ok(2)].into_iter().collect()?;
+            //   |                             ^^^^^^^ cannot infer type
+            //   |
+            //   = note: cannot resolve `<_ as std::ops::Try>::Ok == _`
+            if span.contains(*call_span) {
+                *call_span
+            } else {
+                span
+            }
         } else {
             span
         };
@@ -247,12 +295,11 @@
         //   |         consider giving `b` the explicit type `std::result::Result<i32, E>`, where
         //   |         the type parameter `E` is specified
         // ```
-        let mut err = struct_span_err!(
-            self.tcx.sess,
+        let error_code = error_code.into();
+        let mut err = self.tcx.sess.struct_span_err_with_code(
             err_span,
-            E0282,
-            "type annotations needed{}",
-            ty_msg,
+            &format!("type annotations needed{}", ty_msg),
+            error_code,
         );
 
         let suffix = match local_visitor.found_ty {
@@ -267,6 +314,7 @@
                             &mut err,
                             &decl.output,
                             &body,
+                            &descr,
                             &name,
                             &ret,
                         );
@@ -334,6 +382,36 @@
                 format!("consider giving this pattern {}", suffix)
             };
             err.span_label(pattern.span, msg);
+        } else if let Some(e) = local_visitor.found_method_call {
+            if let ExprKind::MethodCall(segment, ..) = &e.kind {
+                // Suggest specifiying type params or point out the return type of the call:
+                //
+                // error[E0282]: type annotations needed
+                //   --> $DIR/type-annotations-needed-expr.rs:2:39
+                //    |
+                // LL |     let _ = x.into_iter().sum() as f64;
+                //    |                           ^^^
+                //    |                           |
+                //    |                           cannot infer type for `S`
+                //    |                           help: consider specifying the type argument in
+                //    |                           the method call: `sum::<S>`
+                //    |
+                //    = note: type must be known at this point
+                //
+                // or
+                //
+                // error[E0282]: type annotations needed
+                //   --> $DIR/issue-65611.rs:59:20
+                //    |
+                // LL |     let x = buffer.last().unwrap().0.clone();
+                //    |             -------^^^^--
+                //    |             |      |
+                //    |             |      cannot infer type for `T`
+                //    |             this method call resolves to `std::option::Option<&T>`
+                //    |
+                //    = note: type must be known at this point
+                self.annotate_method_call(segment, e, &mut err);
+            }
         }
         // Instead of the following:
         // error[E0282]: type annotations needed
@@ -351,17 +429,66 @@
         //   |               ^^^ cannot infer type for `S`
         //   |
         //   = note: type must be known at this point
-        let span = name_sp.unwrap_or(span);
+        let span = name_sp.unwrap_or(err_span);
         if !err.span.span_labels().iter().any(|span_label| {
                 span_label.label.is_some() && span_label.span == span
             }) && local_visitor.found_arg_pattern.is_none()
         { // Avoid multiple labels pointing at `span`.
-            err.span_label(span, InferCtxt::missing_type_msg(&name));
+            err.span_label(span, InferCtxt::missing_type_msg(&name, &descr));
         }
 
         err
     }
 
+    /// If the `FnSig` for the method call can be found and type arguments are identified as
+    /// needed, suggest annotating the call, otherwise point out the resulting type of the call.
+    fn annotate_method_call(
+        &self,
+        segment: &hir::ptr::P<hir::PathSegment>,
+        e: &Expr,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        if let (Ok(snippet), Some(tables), None) = (
+            self.tcx.sess.source_map().span_to_snippet(segment.ident.span),
+            self.in_progress_tables,
+            &segment.args,
+        ) {
+            let borrow = tables.borrow();
+            if let Some((DefKind::Method, did)) = borrow.type_dependent_def(e.hir_id) {
+                let generics = self.tcx.generics_of(did);
+                if !generics.params.is_empty() {
+                    err.span_suggestion(
+                        segment.ident.span,
+                        &format!(
+                            "consider specifying the type argument{} in the method call",
+                            if generics.params.len() > 1 {
+                                "s"
+                            } else {
+                                ""
+                            },
+                        ),
+                        format!("{}::<{}>", snippet, generics.params.iter()
+                            .map(|p| p.name.to_string())
+                            .collect::<Vec<String>>()
+                            .join(", ")),
+                        Applicability::HasPlaceholders,
+                    );
+                } else {
+                    let sig = self.tcx.fn_sig(did);
+                    let bound_output = sig.output();
+                    let output = bound_output.skip_binder();
+                    err.span_label(e.span, &format!("this method call resolves to `{:?}`", output));
+                    let kind = &output.kind;
+                    if let ty::Projection(proj) | ty::UnnormalizedProjection(proj) = kind {
+                        if let Some(span) = self.tcx.hir().span_if_local(proj.item_def_id) {
+                            err.span_label(span, &format!("`{:?}` defined here", output));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     pub fn need_type_info_err_in_generator(
         &self,
         kind: hir::GeneratorKind,
@@ -369,19 +496,19 @@
         ty: Ty<'tcx>,
     ) -> DiagnosticBuilder<'tcx> {
         let ty = self.resolve_vars_if_possible(&ty);
-        let name = self.extract_type_name(&ty, None).0;
+        let (name, _, descr) = self.extract_type_name(&ty, None);
         let mut err = struct_span_err!(
             self.tcx.sess, span, E0698, "type inside {} must be known in this context", kind,
         );
-        err.span_label(span, InferCtxt::missing_type_msg(&name));
+        err.span_label(span, InferCtxt::missing_type_msg(&name, &descr));
         err
     }
 
-    fn missing_type_msg(type_name: &str) -> String {
+    fn missing_type_msg(type_name: &str, descr: &str) -> Cow<'static, str>{
         if type_name == "_" {
-            "cannot infer type".to_owned()
+            "cannot infer type".into()
         } else {
-            format!("cannot infer type for `{}`", type_name)
+            format!("cannot infer type for {} `{}`", descr, type_name).into()
         }
     }
 }
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index c1f840a..4b93373 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -13,12 +13,20 @@
         match *origin {
             infer::Subtype(ref trace) => {
                 if let Some((expected, found)) = self.values_str(&trace.values) {
-                    let expected = expected.content();
-                    let found = found.content();
-                    err.note(&format!("...so that the {}:\nexpected {}\n   found {}",
-                                      trace.cause.as_requirement_str(),
-                                      expected,
-                                      found));
+                    err.span_note(
+                        trace.cause.span,
+                        &format!(
+                            "...so that the {}",
+                            trace.cause.as_requirement_str()
+                        )
+                    );
+
+                    err.note_expected_found(
+                        &"",
+                        expected,
+                        &"",
+                        found
+                    );
                 } else {
                     // FIXME: this really should be handled at some earlier stage. Our
                     // handling of region checking when type errors are present is
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index b3ddffc..73977878 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1618,37 +1618,37 @@
     // inlined, despite being large, because it has only two call sites that
     // are extremely hot.
     #[inline(always)]
-    pub fn shallow_resolve_changed(&mut self, typ: Ty<'tcx>) -> bool {
-        match typ.kind {
-            ty::Infer(ty::TyVar(v)) => {
+    pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool {
+        match infer {
+            ty::TyVar(v) => {
                 use self::type_variable::TypeVariableValue;
 
-                // See the comment in `shallow_resolve()`.
+                // If `inlined_probe` returns a `Known` value its `kind` never
+                // matches `infer`.
                 match self.infcx.type_variables.borrow_mut().inlined_probe(v) {
-                    TypeVariableValue::Known { value: t } => self.fold_ty(t) != typ,
                     TypeVariableValue::Unknown { .. } => false,
+                    TypeVariableValue::Known { .. } => true,
                 }
             }
 
-            ty::Infer(ty::IntVar(v)) => {
-                match self.infcx.int_unification_table.borrow_mut().inlined_probe_value(v) {
-                    Some(v) => v.to_type(self.infcx.tcx) != typ,
-                    None => false,
-                }
+            ty::IntVar(v) => {
+                // If inlined_probe_value returns a value it's always a
+                // `ty::Int(_)` or `ty::UInt(_)`, which nevers matches a
+                // `ty::Infer(_)`.
+                self.infcx.int_unification_table.borrow_mut().inlined_probe_value(v).is_some()
             }
 
-            ty::Infer(ty::FloatVar(v)) => {
+            ty::FloatVar(v) => {
+                // If inlined_probe_value returns a value it's always a
+                // `ty::Float(_)`, which nevers matches a `ty::Infer(_)`.
+                //
                 // Not `inlined_probe_value(v)` because this call site is colder.
-                match self.infcx.float_unification_table.borrow_mut().probe_value(v) {
-                    Some(v) => v.to_type(self.infcx.tcx) != typ,
-                    None => false,
-                }
+                self.infcx.float_unification_table.borrow_mut().probe_value(v).is_some()
             }
 
-            _ => false,
+            _ => unreachable!(),
         }
     }
-
 }
 
 impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs
index 3110b02..3e28145 100644
--- a/src/librustc/infer/outlives/verify.rs
+++ b/src/librustc/infer/outlives/verify.rs
@@ -211,11 +211,7 @@
                 (r, p)
             );
             let p_ty = p.to_ty(tcx);
-            if compare_ty(p_ty) {
-                Some(ty::OutlivesPredicate(p_ty, r))
-            } else {
-                None
-            }
+            compare_ty(p_ty).then_some(ty::OutlivesPredicate(p_ty, r))
         });
 
         param_bounds
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index e708c5a..24b87ff 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -29,6 +29,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(arbitrary_self_types)]
+#![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(const_fn)]
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 1aba73e..c4bc977 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -329,7 +329,7 @@
 
 declare_lint! {
     pub UNUSED_LABELS,
-    Allow,
+    Warn,
     "detects labels that are never used"
 }
 
diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs
index 95e9f09..0704771 100644
--- a/src/librustc/mir/cache.rs
+++ b/src/librustc/mir/cache.rs
@@ -115,16 +115,16 @@
 }
 
 #[derive(Clone, Debug, HashStable, RustcEncodable, RustcDecodable, TypeFoldable)]
-pub struct BodyCache<'tcx> {
-    cache: Cache,
+pub struct BodyAndCache<'tcx> {
     body: Body<'tcx>,
+    cache: Cache,
 }
 
-impl BodyCache<'tcx> {
+impl BodyAndCache<'tcx> {
     pub fn new(body: Body<'tcx>) -> Self {
         Self {
-            cache: Cache::new(),
             body,
+            cache: Cache::new(),
         }
     }
 }
@@ -139,7 +139,7 @@
     };
 }
 
-impl BodyCache<'tcx> {
+impl BodyAndCache<'tcx> {
     pub fn ensure_predecessors(&mut self) {
         self.cache.ensure_predecessors(&self.body);
     }
@@ -148,8 +148,8 @@
         self.cache.predecessors(&self.body)
     }
 
-    pub fn unwrap_read_only(&self) -> ReadOnlyBodyCache<'_, 'tcx> {
-        ReadOnlyBodyCache::new(&self.cache, &self.body)
+    pub fn unwrap_read_only(&self) -> ReadOnlyBodyAndCache<'_, 'tcx> {
+        ReadOnlyBodyAndCache::new(&self.body, &self.cache)
     }
 
     pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
@@ -163,7 +163,7 @@
     }
 }
 
-impl<'tcx> Index<BasicBlock> for BodyCache<'tcx> {
+impl<'tcx> Index<BasicBlock> for BodyAndCache<'tcx> {
     type Output = BasicBlockData<'tcx>;
 
     fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
@@ -171,13 +171,13 @@
     }
 }
 
-impl<'tcx> IndexMut<BasicBlock> for BodyCache<'tcx> {
+impl<'tcx> IndexMut<BasicBlock> for BodyAndCache<'tcx> {
     fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output {
         &mut self.basic_blocks_mut()[index]
     }
 }
 
-impl<'tcx> Deref for BodyCache<'tcx> {
+impl<'tcx> Deref for BodyAndCache<'tcx> {
     type Target = Body<'tcx>;
 
     fn deref(&self) -> &Self::Target {
@@ -185,26 +185,26 @@
     }
 }
 
-impl<'tcx> DerefMut for BodyCache<'tcx> {
+impl<'tcx> DerefMut for BodyAndCache<'tcx> {
     fn deref_mut(&mut self) -> &mut Self::Target {
         &mut self.body
     }
 }
 
 #[derive(Copy, Clone, Debug)]
-pub struct ReadOnlyBodyCache<'a, 'tcx> {
-    cache: &'a Cache,
+pub struct ReadOnlyBodyAndCache<'a, 'tcx> {
     body: &'a Body<'tcx>,
+    cache: &'a Cache,
 }
 
-impl ReadOnlyBodyCache<'a, 'tcx> {
-    fn new(cache: &'a Cache, body: &'a Body<'tcx>) -> Self {
+impl ReadOnlyBodyAndCache<'a, 'tcx> {
+    fn new(body: &'a Body<'tcx>, cache: &'a Cache) -> Self {
         assert!(
             cache.predecessors.is_some(),
-            "Cannot construct ReadOnlyBodyCache without computed predecessors");
+            "Cannot construct ReadOnlyBodyAndCache without computed predecessors");
         Self {
-            cache,
             body,
+            cache,
         }
     }
 
@@ -220,10 +220,6 @@
         self.cache.unwrap_predecessor_locations(loc, self.body)
     }
 
-    pub fn body(&self) -> &'a Body<'tcx> {
-        self.body
-    }
-
     pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
         &self.body.basic_blocks
     }
@@ -233,16 +229,16 @@
     }
 }
 
-impl graph::DirectedGraph for ReadOnlyBodyCache<'a, 'tcx> {
+impl graph::DirectedGraph for ReadOnlyBodyAndCache<'a, 'tcx> {
     type Node = BasicBlock;
 }
 
-impl graph::GraphPredecessors<'graph> for ReadOnlyBodyCache<'a, 'tcx> {
+impl graph::GraphPredecessors<'graph> for ReadOnlyBodyAndCache<'a, 'tcx> {
     type Item = BasicBlock;
     type Iter = IntoIter<BasicBlock>;
 }
 
-impl graph::WithPredecessors for ReadOnlyBodyCache<'a, 'tcx> {
+impl graph::WithPredecessors for ReadOnlyBodyAndCache<'a, 'tcx> {
     fn predecessors(
         &self,
         node: Self::Node,
@@ -251,19 +247,19 @@
     }
 }
 
-impl graph::WithNumNodes for ReadOnlyBodyCache<'a, 'tcx> {
+impl graph::WithNumNodes for ReadOnlyBodyAndCache<'a, 'tcx> {
     fn num_nodes(&self) -> usize {
         self.body.num_nodes()
     }
 }
 
-impl graph::WithStartNode for ReadOnlyBodyCache<'a, 'tcx> {
+impl graph::WithStartNode for ReadOnlyBodyAndCache<'a, 'tcx> {
     fn start_node(&self) -> Self::Node {
         self.body.start_node()
     }
 }
 
-impl graph::WithSuccessors for ReadOnlyBodyCache<'a, 'tcx> {
+impl graph::WithSuccessors for ReadOnlyBodyAndCache<'a, 'tcx> {
     fn successors(
         &self,
         node: Self::Node,
@@ -272,13 +268,13 @@
     }
 }
 
-impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for ReadOnlyBodyCache<'a, 'tcx> {
+impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for ReadOnlyBodyAndCache<'a, 'tcx> {
     type Item = BasicBlock;
     type Iter = iter::Cloned<Successors<'b>>;
 }
 
 
-impl Deref for ReadOnlyBodyCache<'a, 'tcx> {
+impl Deref for ReadOnlyBodyAndCache<'a, 'tcx> {
     type Target = &'a Body<'tcx>;
 
     fn deref(&self) -> &Self::Target {
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 5573106..0dec7c0 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -370,6 +370,14 @@
     Unreachable,
     /// An enum discriminant was set to a value which was outside the range of valid values.
     InvalidDiscriminant(ScalarMaybeUndef),
+    /// A slice/array index projection went out-of-bounds.
+    BoundsCheckFailed { len: u64, index: u64 },
+    /// Something was divided by 0 (x / 0).
+    DivisionByZero,
+    /// Something was "remainded" by 0 (x % 0).
+    RemainderByZero,
+    /// Overflowing inbounds pointer arithmetic.
+    PointerArithOverflow,
 }
 
 impl fmt::Debug for UndefinedBehaviorInfo {
@@ -379,9 +387,18 @@
             Ub(msg) | UbExperimental(msg) =>
                 write!(f, "{}", msg),
             Unreachable =>
-                write!(f, "entered unreachable code"),
+                write!(f, "entering unreachable code"),
             InvalidDiscriminant(val) =>
-                write!(f, "encountered invalid enum discriminant {}", val),
+                write!(f, "encountering invalid enum discriminant {}", val),
+            BoundsCheckFailed { ref len, ref index } =>
+                write!(f, "indexing out of bounds: the len is {:?} but the index is {:?}",
+                    len, index),
+            DivisionByZero =>
+                write!(f, "dividing by zero"),
+            RemainderByZero =>
+                write!(f, "calculating the remainder with a divisor of zero"),
+            PointerArithOverflow =>
+                write!(f, "overflowing in-bounds pointer arithmetic"),
         }
     }
 }
diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs
index 78320c7..0b27f51 100644
--- a/src/librustc/mir/interpret/pointer.rs
+++ b/src/librustc/mir/interpret/pointer.rs
@@ -1,6 +1,5 @@
 use super::{AllocId, InterpResult};
 
-use crate::mir;
 use crate::ty::layout::{self, HasDataLayout, Size};
 
 use rustc_macros::HashStable;
@@ -88,13 +87,13 @@
     #[inline]
     fn offset<'tcx>(&self, val: u64, i: u64) -> InterpResult<'tcx, u64> {
         let (res, over) = self.overflowing_offset(val, i);
-        if over { throw_panic!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+        if over { throw_ub!(PointerArithOverflow) } else { Ok(res) }
     }
 
     #[inline]
     fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> {
         let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
-        if over { throw_panic!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+        if over { throw_ub!(PointerArithOverflow) } else { Ok(res) }
     }
 }
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index df5d499..ba8feb4 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -38,7 +38,7 @@
 use syntax_pos::{Span, DUMMY_SP};
 
 pub use crate::mir::interpret::AssertMessage;
-pub use crate::mir::cache::{BodyCache, ReadOnlyBodyCache};
+pub use crate::mir::cache::{BodyAndCache, ReadOnlyBodyAndCache};
 pub use crate::read_only;
 
 mod cache;
@@ -108,7 +108,7 @@
     pub yield_ty: Option<Ty<'tcx>>,
 
     /// Generator drop glue.
-    pub generator_drop: Option<Box<BodyCache<'tcx>>>,
+    pub generator_drop: Option<Box<BodyAndCache<'tcx>>>,
 
     /// The layout of a generator. Produced by the state transformation.
     pub generator_layout: Option<GeneratorLayout<'tcx>>,
@@ -242,11 +242,7 @@
     pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
         (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
-            if self.local_decls[local].is_user_variable() {
-                Some(local)
-            } else {
-                None
-            }
+            self.local_decls[local].is_user_variable().then_some(local)
         })
     }
 
@@ -282,15 +278,15 @@
 
     /// Returns an iterator over all function arguments.
     #[inline]
-    pub fn args_iter(&self) -> impl Iterator<Item = Local> {
+    pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
         let arg_count = self.arg_count;
-        (1..=arg_count).map(Local::new)
+        (1..arg_count + 1).map(Local::new)
     }
 
     /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
     /// locals that are neither arguments nor the return place).
     #[inline]
-    pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> {
+    pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
         let arg_count = self.arg_count;
         let local_count = self.local_decls.len();
         (arg_count + 1..local_count).map(Local::new)
@@ -1718,18 +1714,25 @@
     ConstantIndex {
         /// index or -index (in Python terms), depending on from_end
         offset: u32,
-        /// thing being indexed must be at least this long
+        /// The thing being indexed must be at least this long. For arrays this
+        /// is always the exact length.
         min_length: u32,
-        /// counting backwards from end?
+        /// Counting backwards from end? This is always false when indexing an
+        /// array.
         from_end: bool,
     },
 
     /// These indices are generated by slice patterns.
     ///
-    /// slice[from:-to] in Python terms.
+    /// If `from_end` is true `slice[from..slice.len() - to]`.
+    /// Otherwise `array[from..to]`.
     Subslice {
         from: u32,
         to: u32,
+        /// Whether `to` counts from the start or end of the array/slice.
+        /// For `PlaceElem`s this is `true` if and only if the base is a slice.
+        /// For `ProjectionKind`, this can also be `true` for arrays.
+        from_end: bool,
     },
 
     /// "Downcast" to a variant of an ADT. Currently, we only introduce
@@ -1918,15 +1921,18 @@
                 ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => {
                     write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
                 }
-                ProjectionElem::Subslice { from, to } if *to == 0 => {
+                ProjectionElem::Subslice { from, to, from_end: true } if *to == 0 => {
                     write!(fmt, "[{:?}:]", from)?;
                 }
-                ProjectionElem::Subslice { from, to } if *from == 0 => {
+                ProjectionElem::Subslice { from, to, from_end: true } if *from == 0 => {
                     write!(fmt, "[:-{:?}]", to)?;
                 }
-                ProjectionElem::Subslice { from, to } => {
+                ProjectionElem::Subslice { from, to, from_end: true } => {
                     write!(fmt, "[{:?}:-{:?}]", from, to)?;
                 }
+                ProjectionElem::Subslice { from, to, from_end: false } => {
+                    write!(fmt, "[{:?}..{:?}]", from, to)?;
+                }
             }
         }
 
@@ -2384,11 +2390,15 @@
         UserTypeProjections { contents: projs.collect() }
     }
 
-    pub fn projections_and_spans(&self) -> impl Iterator<Item = &(UserTypeProjection, Span)> {
+    pub fn projections_and_spans(&self)
+        -> impl Iterator<Item = &(UserTypeProjection, Span)> + ExactSizeIterator
+    {
         self.contents.iter()
     }
 
-    pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> {
+    pub fn projections(&self)
+        -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator
+    {
         self.contents.iter().map(|&(ref user_type, _span)| user_type)
     }
 
@@ -2456,7 +2466,7 @@
     }
 
     pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self {
-        self.projs.push(ProjectionElem::Subslice { from, to });
+        self.projs.push(ProjectionElem::Subslice { from, to, from_end: true });
         self
     }
 
@@ -2601,7 +2611,7 @@
     pub fn is_predecessor_of<'tcx>(
         &self,
         other: Location,
-        body: ReadOnlyBodyCache<'_, 'tcx>
+        body: ReadOnlyBodyAndCache<'_, 'tcx>
     ) -> bool {
         // If we are in the same block as the other location and are an earlier statement
         // then we are a predecessor of `other`.
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index a66a49f..445fa6e 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -88,14 +88,17 @@
             }
             ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
                 PlaceTy::from_ty(self.ty.builtin_index().unwrap()),
-            ProjectionElem::Subslice { from, to } => {
+            ProjectionElem::Subslice { from, to, from_end } => {
                 PlaceTy::from_ty(match self.ty.kind {
-                    ty::Array(inner, size) => {
+                    ty::Slice(..) => self.ty,
+                    ty::Array(inner, _) if !from_end => {
+                        tcx.mk_array(inner, (to - from) as u64)
+                    }
+                    ty::Array(inner, size) if from_end => {
                         let size = size.eval_usize(tcx, param_env);
                         let len = size - (from as u64) - (to as u64);
                         tcx.mk_array(inner, len)
                     }
-                    ty::Slice(..) => self.ty,
                     _ => {
                         bug!("cannot subslice non-array type: `{:?}`", self)
                     }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 47a1d67..5d273fe 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -67,10 +67,10 @@
 
 macro_rules! body_cache_type {
     (mut $a:lifetime, $tcx:lifetime) => {
-        &mut BodyCache<$tcx>
+        &mut BodyAndCache<$tcx>
     };
     ($a:lifetime, $tcx:lifetime) => {
-        ReadOnlyBodyCache<$a, $tcx>
+        ReadOnlyBodyAndCache<$a, $tcx>
     };
 }
 
@@ -954,7 +954,7 @@
                     );
                 }
                 ProjectionElem::Deref |
-                ProjectionElem::Subslice { from: _, to: _ } |
+                ProjectionElem::Subslice { from: _, to: _, from_end: _ } |
                 ProjectionElem::ConstantIndex { offset: _,
                                                 min_length: _,
                                                 from_end: _ } |
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index a6d7e5c..538b13c 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -106,30 +106,30 @@
 
         /// Fetch the MIR for a given `DefId` right after it's built - this includes
         /// unreachable code.
-        query mir_built(_: DefId) -> &'tcx Steal<mir::BodyCache<'tcx>> {}
+        query mir_built(_: DefId) -> &'tcx Steal<mir::BodyAndCache<'tcx>> {}
 
         /// Fetch the MIR for a given `DefId` up till the point where it is
         /// ready for const evaluation.
         ///
         /// See the README for the `mir` module for details.
-        query mir_const(_: DefId) -> &'tcx Steal<mir::BodyCache<'tcx>> {
+        query mir_const(_: DefId) -> &'tcx Steal<mir::BodyAndCache<'tcx>> {
             no_hash
         }
 
         query mir_validated(_: DefId) ->
             (
-                &'tcx Steal<mir::BodyCache<'tcx>>,
-                &'tcx Steal<IndexVec<mir::Promoted, mir::BodyCache<'tcx>>>
+                &'tcx Steal<mir::BodyAndCache<'tcx>>,
+                &'tcx Steal<IndexVec<mir::Promoted, mir::BodyAndCache<'tcx>>>
             ) {
             no_hash
         }
 
         /// MIR after our optimization passes have run. This is MIR that is ready
         /// for codegen. This is also the only query that can fetch non-local MIR, at present.
-        query optimized_mir(key: DefId) -> &'tcx mir::BodyCache<'tcx> {
+        query optimized_mir(key: DefId) -> &'tcx mir::BodyAndCache<'tcx> {
             cache_on_disk_if { key.is_local() }
             load_cached(tcx, id) {
-                let mir: Option<crate::mir::BodyCache<'tcx>>
+                let mir: Option<crate::mir::BodyAndCache<'tcx>>
                     = tcx.queries.on_disk_cache.try_load_query_result(tcx, id);
                 mir.map(|x| {
                     let cache = tcx.arena.alloc(x);
@@ -139,13 +139,13 @@
             }
         }
 
-        query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::BodyCache<'tcx>> {
+        query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::BodyAndCache<'tcx>> {
             cache_on_disk_if { key.is_local() }
             load_cached(tcx, id) {
                 let promoted: Option<
                     rustc_index::vec::IndexVec<
                         crate::mir::Promoted,
-                        crate::mir::BodyCache<'tcx>
+                        crate::mir::BodyAndCache<'tcx>
                     >> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id);
                 promoted.map(|p| {
                     let cache = tcx.arena.alloc(p);
@@ -512,7 +512,7 @@
         /// in the case of closures, this will be redirected to the enclosing function.
         query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {}
 
-        query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyCache<'tcx> {
+        query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyAndCache<'tcx> {
             no_force
             desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
         }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index ba44c6c..da36b31 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -22,9 +22,11 @@
 use crate::hir::Node;
 use crate::hir::def_id::DefId;
 use crate::infer::{self, InferCtxt};
+use crate::infer::error_reporting::TypeAnnotationNeeded as ErrorCode;
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::session::DiagnosticMessageId;
 use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
+use crate::ty::TypeckTables;
 use crate::ty::GenericParamDefKind;
 use crate::ty::error::ExpectedFound;
 use crate::ty::fast_reject;
@@ -363,11 +365,7 @@
             return None
         };
 
-        if tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented) {
-            Some(impl_def_id)
-        } else {
-            None
-        }
+        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
     }
 
     fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
@@ -1955,7 +1953,7 @@
             return;
         }
 
-        match predicate {
+        let mut err = match predicate {
             ty::Predicate::Trait(ref data) => {
                 let trait_ref = data.to_poly_trait_ref();
                 let self_ty = trait_ref.self_ty();
@@ -1989,59 +1987,109 @@
                 // avoid inundating the user with unnecessary errors, but we now
                 // check upstream for type errors and dont add the obligations to
                 // begin with in those cases.
-                if
-                    self.tcx.lang_items().sized_trait()
+                if self.tcx.lang_items().sized_trait()
                     .map_or(false, |sized_id| sized_id == trait_ref.def_id())
                 {
-                    self.need_type_info_err(body_id, span, self_ty).emit();
-                } else {
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        span,
-                        E0283,
-                        "type annotations needed: cannot resolve `{}`",
-                        predicate,
-                    );
-                    self.note_obligation_cause(&mut err, obligation);
-                    err.emit();
+                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
+                    return;
                 }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                if let (Ok(ref snippet), ObligationCauseCode::BindingObligation(ref def_id, _)) = (
+                    self.tcx.sess.source_map().span_to_snippet(span),
+                    &obligation.cause.code,
+                ) {
+                    let generics = self.tcx.generics_of(*def_id);
+                    if !generics.params.is_empty() && !snippet.ends_with('>'){
+                        // FIXME: To avoid spurious suggestions in functions where type arguments
+                        // where already supplied, we check the snippet to make sure it doesn't
+                        // end with a turbofish. Ideally we would have access to a `PathSegment`
+                        // instead. Otherwise we would produce the following output:
+                        //
+                        // error[E0283]: type annotations needed
+                        //   --> $DIR/issue-54954.rs:3:24
+                        //    |
+                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
+                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+                        //    |                        |
+                        //    |                        cannot infer type
+                        //    |                        help: consider specifying the type argument
+                        //    |                        in the function call:
+                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
+                        // ...
+                        // LL |     const fn const_val<T: Sized>() -> usize {
+                        //    |              --------- - required by this bound in `Tt::const_val`
+                        //    |
+                        //    = note: cannot resolve `_: Tt`
+
+                        err.span_suggestion(
+                            span,
+                            &format!(
+                                "consider specifying the type argument{} in the function call",
+                                if generics.params.len() > 1 {
+                                    "s"
+                                } else {
+                                    ""
+                                },
+                            ),
+                            format!("{}::<{}>", snippet, generics.params.iter()
+                                .map(|p| p.name.to_string())
+                                .collect::<Vec<String>>()
+                                .join(", ")),
+                            Applicability::HasPlaceholders,
+                        );
+                    }
+                }
+                err
             }
 
             ty::Predicate::WellFormed(ty) => {
                 // Same hacky approach as above to avoid deluging user
                 // with error messages.
-                if !ty.references_error() && !self.tcx.sess.has_errors() {
-                    self.need_type_info_err(body_id, span, ty).emit();
+                if ty.references_error() || self.tcx.sess.has_errors() {
+                    return;
                 }
+                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
             }
 
             ty::Predicate::Subtype(ref data) => {
                 if data.references_error() || self.tcx.sess.has_errors() {
                     // no need to overload user in such cases
-                } else {
-                    let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
-                    // both must be type variables, or the other would've been instantiated
-                    assert!(a.is_ty_var() && b.is_ty_var());
-                    self.need_type_info_err(body_id,
-                                            obligation.cause.span,
-                                            a).emit();
+                    return
                 }
+                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                // both must be type variables, or the other would've been instantiated
+                assert!(a.is_ty_var() && b.is_ty_var());
+                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
+            }
+            ty::Predicate::Projection(ref data) => {
+                let trait_ref = data.to_poly_trait_ref(self.tcx);
+                let self_ty = trait_ref.self_ty();
+                if predicate.references_error() {
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                err
             }
 
             _ => {
-                if !self.tcx.sess.has_errors() {
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        obligation.cause.span,
-                        E0284,
-                        "type annotations needed: cannot resolve `{}`",
-                        predicate,
-                    );
-                    self.note_obligation_cause(&mut err, obligation);
-                    err.emit();
+                if self.tcx.sess.has_errors() {
+                    return;
                 }
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0284,
+                    "type annotations needed: cannot resolve `{}`",
+                    predicate,
+                );
+                err.span_label(span, &format!("cannot resolve `{}`", predicate));
+                err
             }
-        }
+        };
+        self.note_obligation_cause(&mut err, obligation);
+        err.emit();
     }
 
     /// Returns `true` if the trait predicate may apply for *some* assignment
@@ -2108,52 +2156,69 @@
     ) {
         // First, attempt to add note to this error with an async-await-specific
         // message, and fall back to regular note otherwise.
-        if !self.note_obligation_cause_for_async_await(err, obligation) {
+        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
             self.note_obligation_cause_code(err, &obligation.predicate, &obligation.cause.code,
                                             &mut vec![]);
         }
     }
 
-    /// Adds an async-await specific note to the diagnostic:
+    /// Adds an async-await specific note to the diagnostic when the future does not implement
+    /// an auto trait because of a captured type.
     ///
     /// ```ignore (diagnostic)
-    /// note: future does not implement `std::marker::Send` because this value is used across an
-    ///       await
-    ///   --> $DIR/issue-64130-non-send-future-diags.rs:15:5
+    /// note: future does not implement `Qux` as this value is used across an await
+    ///   --> $DIR/issue-64130-3-other.rs:17:5
     ///    |
-    /// LL |     let g = x.lock().unwrap();
-    ///    |         - has type `std::sync::MutexGuard<'_, u32>`
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
     /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `g` maybe used later
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
     /// LL | }
-    ///    | - `g` is later dropped here
+    ///    | - `x` is later dropped here
+    /// ```
+    ///
+    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
+    /// is "replaced" with a different message and a more specific error.
+    ///
+    /// ```ignore (diagnostic)
+    /// error: future cannot be sent between threads safely
+    ///   --> $DIR/issue-64130-2-send.rs:21:5
+    ///    |
+    /// LL | fn is_send<T: Send>(t: T) { }
+    ///    |    -------    ---- required by this bound in `is_send`
+    /// ...
+    /// LL |     is_send(bar());
+    ///    |     ^^^^^^^ future returned by `bar` is not send
+    ///    |
+    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
+    ///            implemented for `Foo`
+    /// note: future is not send as this value is used across an await
+    ///   --> $DIR/issue-64130-2-send.rs:15:5
+    ///    |
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
+    /// LL |     baz().await;
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+    /// LL | }
+    ///    | - `x` is later dropped here
     /// ```
     ///
     /// Returns `true` if an async-await specific note was added to the diagnostic.
-    fn note_obligation_cause_for_async_await(
+    fn maybe_note_obligation_cause_for_async_await(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         obligation: &PredicateObligation<'tcx>,
     ) -> bool {
-        debug!("note_obligation_cause_for_async_await: obligation.predicate={:?} \
+        debug!("maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
                 obligation.cause.span={:?}", obligation.predicate, obligation.cause.span);
         let source_map = self.tcx.sess.source_map();
 
-        // Look into the obligation predicate to determine the type in the generator which meant
-        // that the predicate was not satisifed.
-        let (trait_ref, target_ty) = match obligation.predicate {
-            ty::Predicate::Trait(trait_predicate) =>
-                (trait_predicate.skip_binder().trait_ref, trait_predicate.skip_binder().self_ty()),
-            _ => return false,
-        };
-        debug!("note_obligation_cause_for_async_await: target_ty={:?}", target_ty);
-
         // Attempt to detect an async-await error by looking at the obligation causes, looking
-        // for only generators, generator witnesses, opaque types or `std::future::GenFuture` to
-        // be present.
+        // for a generator to be present.
         //
         // When a future does not implement a trait because of a captured type in one of the
         // generators somewhere in the call stack, then the result is a chain of obligations.
+        //
         // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
         // future is passed as an argument to a function C which requires a `Send` type, then the
         // chain looks something like this:
@@ -2170,98 +2235,224 @@
         // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
         // - `BindingObligation` with `impl_send (Send requirement)
         //
-        // The first obligations in the chain can be used to get the details of the type that is
-        // captured but the entire chain must be inspected to detect this case.
+        // The first obligation in the chain is the most useful and has the generator that captured
+        // the type. The last generator has information about where the bound was introduced. At
+        // least one generator should be present for this diagnostic to be modified.
+        let (mut trait_ref, mut target_ty) = match obligation.predicate {
+            ty::Predicate::Trait(p) =>
+                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty())),
+            _ => (None, None),
+        };
         let mut generator = None;
+        let mut last_generator = None;
         let mut next_code = Some(&obligation.cause.code);
         while let Some(code) = next_code {
-            debug!("note_obligation_cause_for_async_await: code={:?}", code);
+            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
             match code {
                 ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) |
                 ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
-                    debug!("note_obligation_cause_for_async_await: self_ty.kind={:?}",
-                           derived_obligation.parent_trait_ref.self_ty().kind);
-                    match derived_obligation.parent_trait_ref.self_ty().kind {
-                        ty::Adt(ty::AdtDef { did, .. }, ..) if
-                            self.tcx.is_diagnostic_item(sym::gen_future, *did) => {},
-                        ty::Generator(did, ..) => generator = generator.or(Some(did)),
-                        ty::GeneratorWitness(_) | ty::Opaque(..) => {},
-                        _ => return false,
+                    let ty = derived_obligation.parent_trait_ref.self_ty();
+                    debug!("maybe_note_obligation_cause_for_async_await: \
+                            parent_trait_ref={:?} self_ty.kind={:?}",
+                           derived_obligation.parent_trait_ref, ty.kind);
+
+                    match ty.kind {
+                        ty::Generator(did, ..) => {
+                            generator = generator.or(Some(did));
+                            last_generator = Some(did);
+                        },
+                        ty::GeneratorWitness(..) => {},
+                        _ if generator.is_none() => {
+                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
+                            target_ty = Some(ty);
+                        },
+                        _ => {},
                     }
 
                     next_code = Some(derived_obligation.parent_code.as_ref());
                 },
-                ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(..)
-                    if generator.is_some() => break,
-                _ => return false,
+                _ => break,
             }
         }
 
-        let generator_did = generator.expect("can only reach this if there was a generator");
-
-        // Only continue to add a note if the generator is from an `async` function.
-        let parent_node = self.tcx.parent(generator_did)
-            .and_then(|parent_did| self.tcx.hir().get_if_local(parent_did));
-        debug!("note_obligation_cause_for_async_await: parent_node={:?}", parent_node);
-        if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, _),
-            ..
-        })) = parent_node {
-            debug!("note_obligation_cause_for_async_await: header={:?}", sig.header);
-            if sig.header.asyncness != hir::IsAsync::Async {
-                return false;
-            }
-        }
+        // Only continue if a generator was found.
+        debug!("maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
+                target_ty={:?}", generator, trait_ref, target_ty);
+        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
+            (Some(generator_did), Some(trait_ref), Some(target_ty)) =>
+                (generator_did, trait_ref, target_ty),
+            _ => return false,
+        };
 
         let span = self.tcx.def_span(generator_did);
-        let tables = self.tcx.typeck_tables_of(generator_did);
-        debug!("note_obligation_cause_for_async_await: generator_did={:?} span={:?} ",
-               generator_did, span);
+
+        // Do not ICE on closure typeck (#66868).
+        if let None = self.tcx.hir().as_local_hir_id(generator_did) {
+            return false;
+        }
+
+        // Get the tables from the infcx if the generator is the function we are
+        // currently type-checking; otherwise, get them by performing a query.
+        // This is needed to avoid cycles.
+        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
+        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
+        debug!("maybe_note_obligation_cause_for_async_await: generator_did={:?} \
+             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
+            generator_did, generator_did_root,
+            in_progress_tables.as_ref().map(|t| t.local_id_root), span);
+        let query_tables;
+        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
+            Some(t) if t.local_id_root == Some(generator_did_root) => t,
+            _ => {
+                query_tables = self.tcx.typeck_tables_of(generator_did);
+                &query_tables
+            }
+        };
 
         // Look for a type inside the generator interior that matches the target type to get
         // a span.
+        let target_ty_erased = self.tcx.erase_regions(&target_ty);
         let target_span = tables.generator_interior_types.iter()
-            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| ty::TyS::same_type(*ty, target_ty))
+            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
+                // Careful: the regions for types that appear in the
+                // generator interior are not generally known, so we
+                // want to erase them when comparing (and anyway,
+                // `Send` and other bounds are generally unaffected by
+                // the choice of region).  When erasing regions, we
+                // also have to erase late-bound regions. This is
+                // because the types that appear in the generator
+                // interior generally contain "bound regions" to
+                // represent regions that are part of the suspended
+                // generator frame. Bound regions are preserved by
+                // `erase_regions` and so we must also call
+                // `erase_late_bound_regions`.
+                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
+                let ty_erased = self.tcx.erase_regions(&ty_erased);
+                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
+                debug!("maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
+                        target_ty_erased={:?} eq={:?}", ty_erased, target_ty_erased, eq);
+                eq
+            })
             .map(|ty::GeneratorInteriorTypeCause { span, scope_span, .. }|
                  (span, source_map.span_to_snippet(*span), scope_span));
+        debug!("maybe_note_obligation_cause_for_async_await: target_ty={:?} \
+                generator_interior_types={:?} target_span={:?}",
+                target_ty, tables.generator_interior_types, target_span);
         if let Some((target_span, Ok(snippet), scope_span)) = target_span {
-            // Look at the last interior type to get a span for the `.await`.
-            let await_span = tables.generator_interior_types.iter().map(|i| i.span).last().unwrap();
-            let mut span = MultiSpan::from_span(await_span);
-            span.push_span_label(
-                await_span, format!("await occurs here, with `{}` maybe used later", snippet));
-
-            span.push_span_label(*target_span, format!("has type `{}`", target_ty));
-
-            // If available, use the scope span to annotate the drop location.
-            if let Some(scope_span) = scope_span {
-                span.push_span_label(
-                    source_map.end_point(*scope_span),
-                    format!("`{}` is later dropped here", snippet),
-                );
-            }
-
-            err.span_note(span, &format!(
-                "future does not implement `{}` as this value is used across an await",
-                trait_ref.print_only_trait_path(),
-            ));
-
-            // Add a note for the item obligation that remains - normally a note pointing to the
-            // bound that introduced the obligation (e.g. `T: Send`).
-            debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
-            self.note_obligation_cause_code(
-                err,
-                &obligation.predicate,
-                next_code.unwrap(),
-                &mut Vec::new(),
+            self.note_obligation_cause_for_async_await(
+                err, *target_span, scope_span, snippet, generator_did, last_generator,
+                trait_ref, target_ty, tables, obligation, next_code,
             );
-
             true
         } else {
             false
         }
     }
 
+    /// Unconditionally adds the diagnostic note described in
+    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
+    fn note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        target_span: Span,
+        scope_span: &Option<Span>,
+        snippet: String,
+        first_generator: DefId,
+        last_generator: Option<DefId>,
+        trait_ref: ty::TraitRef<'_>,
+        target_ty: Ty<'tcx>,
+        tables: &ty::TypeckTables<'_>,
+        obligation: &PredicateObligation<'tcx>,
+        next_code: Option<&ObligationCauseCode<'tcx>>,
+    ) {
+        let source_map = self.tcx.sess.source_map();
+
+        let is_async_fn = self.tcx.parent(first_generator)
+            .map(|parent_did| self.tcx.asyncness(parent_did))
+            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
+            .unwrap_or(false);
+        let is_async_move = self.tcx.hir().as_local_hir_id(first_generator)
+            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
+            .map(|body_id| self.tcx.hir().body(body_id))
+            .and_then(|body| body.generator_kind())
+            .map(|generator_kind| match generator_kind {
+                hir::GeneratorKind::Async(..) => true,
+                _ => false,
+            })
+            .unwrap_or(false);
+        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
+
+        // Special case the primary error message when send or sync is the trait that was
+        // not implemented.
+        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
+        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
+        let trait_explanation = if is_send || is_sync {
+            let (trait_name, trait_verb) = if is_send {
+                ("`Send`", "sent")
+            } else {
+                ("`Sync`", "shared")
+            };
+
+            err.clear_code();
+            err.set_primary_message(
+                format!("future cannot be {} between threads safely", trait_verb)
+            );
+
+            let original_span = err.span.primary_span().unwrap();
+            let mut span = MultiSpan::from_span(original_span);
+
+            let message = if let Some(name) = last_generator
+                .and_then(|generator_did| self.tcx.parent(generator_did))
+                .and_then(|parent_did| self.tcx.hir().as_local_hir_id(parent_did))
+                .map(|parent_hir_id| self.tcx.hir().name(parent_hir_id))
+            {
+                format!("future returned by `{}` is not {}", name, trait_name)
+            } else {
+                format!("future is not {}", trait_name)
+            };
+
+            span.push_span_label(original_span, message);
+            err.set_span(span);
+
+            format!("is not {}", trait_name)
+        } else {
+            format!("does not implement `{}`", trait_ref.print_only_trait_path())
+        };
+
+        // Look at the last interior type to get a span for the `.await`.
+        let await_span = tables.generator_interior_types.iter().map(|i| i.span).last().unwrap();
+        let mut span = MultiSpan::from_span(await_span);
+        span.push_span_label(
+            await_span,
+            format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet));
+
+        span.push_span_label(target_span, format!("has type `{}`", target_ty));
+
+        // If available, use the scope span to annotate the drop location.
+        if let Some(scope_span) = scope_span {
+            span.push_span_label(
+                source_map.end_point(*scope_span),
+                format!("`{}` is later dropped here", snippet),
+            );
+        }
+
+        err.span_note(span, &format!(
+            "future {} as this value is used across an {}",
+            trait_explanation,
+            await_or_yield,
+        ));
+
+        // Add a note for the item obligation that remains - normally a note pointing to the
+        // bound that introduced the obligation (e.g. `T: Send`).
+        debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
+        self.note_obligation_cause_code(
+            err,
+            &obligation.predicate,
+            next_code.unwrap(),
+            &mut Vec::new(),
+        );
+    }
+
     fn note_obligation_cause_code<T>(&self,
                                      err: &mut DiagnosticBuilder<'_>,
                                      predicate: &T,
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index a981162..2773199 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -65,7 +65,7 @@
 #[derive(Clone, Debug)]
 pub struct PendingPredicateObligation<'tcx> {
     pub obligation: PredicateObligation<'tcx>,
-    pub stalled_on: Vec<Ty<'tcx>>,
+    pub stalled_on: Vec<ty::InferTy>,
 }
 
 // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -263,8 +263,8 @@
             // Match arms are in order of frequency, which matters because this
             // code is so hot. 1 and 0 dominate; 2+ is fairly rare.
             1 => {
-                let ty = pending_obligation.stalled_on[0];
-                ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty)
+                let infer = pending_obligation.stalled_on[0];
+                ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
             }
             0 => {
                 // In this case we haven't changed, but wish to make a change.
@@ -274,8 +274,8 @@
                 // This `for` loop was once a call to `all()`, but this lower-level
                 // form was a perf win. See #64545 for details.
                 (|| {
-                    for &ty in &pending_obligation.stalled_on {
-                        if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) {
+                    for &infer in &pending_obligation.stalled_on {
+                        if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) {
                             return true;
                         }
                     }
@@ -305,6 +305,13 @@
 
         debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
 
+        fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
+            match ty.kind {
+                ty::Infer(infer) => infer,
+                _ => panic!(),
+            }
+        }
+
         match obligation.predicate {
             ty::Predicate::Trait(ref data) => {
                 let trait_obligation = obligation.with(data.clone());
@@ -459,7 +466,7 @@
                     obligation.cause.span,
                 ) {
                     None => {
-                        pending_obligation.stalled_on = vec![ty];
+                        pending_obligation.stalled_on = vec![infer_ty(ty)];
                         ProcessResult::Unchanged
                     }
                     Some(os) => ProcessResult::Changed(mk_pending(os))
@@ -472,8 +479,8 @@
                                                            subtype) {
                     None => {
                         // None means that both are unresolved.
-                        pending_obligation.stalled_on = vec![subtype.skip_binder().a,
-                                                             subtype.skip_binder().b];
+                        pending_obligation.stalled_on = vec![infer_ty(subtype.skip_binder().a),
+                                                             infer_ty(subtype.skip_binder().b)];
                         ProcessResult::Unchanged
                     }
                     Some(Ok(ok)) => {
@@ -517,7 +524,8 @@
                             ))
                         }
                     } else {
-                        pending_obligation.stalled_on = substs.types().collect();
+                        pending_obligation.stalled_on =
+                            substs.types().map(|ty| infer_ty(ty)).collect();
                         ProcessResult::Unchanged
                     }
                 }
@@ -542,13 +550,13 @@
 fn trait_ref_type_vars<'a, 'tcx>(
     selcx: &mut SelectionContext<'a, 'tcx>,
     t: ty::PolyTraitRef<'tcx>,
-) -> Vec<Ty<'tcx>> {
+) -> Vec<ty::InferTy> {
     t.skip_binder() // ok b/c this check doesn't care about regions
      .input_types()
      .map(|t| selcx.infcx().resolve_vars_if_possible(&t))
      .filter(|t| t.has_infer_types())
      .flat_map(|t| t.walk())
-     .filter(|t| match t.kind { ty::Infer(_) => true, _ => false })
+     .filter_map(|t| match t.kind { ty::Infer(infer) => Some(infer), _ => None })
      .collect()
 }
 
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index c345b9a..1fdec5f 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1079,12 +1079,10 @@
                 if !is_default {
                     true
                 } else if obligation.param_env.reveal == Reveal::All {
-                    debug_assert!(!poly_trait_ref.needs_infer());
-                    if !poly_trait_ref.needs_subst() {
-                        true
-                    } else {
-                        false
-                    }
+                    // NOTE(eddyb) inference variables can resolve to parameters, so
+                    // assume `poly_trait_ref` isn't monomorphic, if it contains any.
+                    let poly_trait_ref = selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
+                    !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
                 } else {
                     false
                 }
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 5f32452..94a77c5 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -204,7 +204,10 @@
 #[derive(Clone, Default)]
 pub struct SelectionCache<'tcx> {
     hashmap: Lock<
-        FxHashMap<ty::TraitRef<'tcx>, WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>,
+        FxHashMap<
+            ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
+            WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>,
+        >,
     >,
 }
 
@@ -490,7 +493,9 @@
 
 #[derive(Clone, Default)]
 pub struct EvaluationCache<'tcx> {
-    hashmap: Lock<FxHashMap<ty::PolyTraitRef<'tcx>, WithDepNode<EvaluationResult>>>,
+    hashmap: Lock<
+        FxHashMap<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, WithDepNode<EvaluationResult>>,
+    >,
 }
 
 impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
@@ -1143,7 +1148,7 @@
         let tcx = self.tcx();
         if self.can_use_global_caches(param_env) {
             let cache = tcx.evaluation_cache.hashmap.borrow();
-            if let Some(cached) = cache.get(&trait_ref) {
+            if let Some(cached) = cache.get(&param_env.and(trait_ref)) {
                 return Some(cached.get(tcx));
             }
         }
@@ -1151,7 +1156,7 @@
             .evaluation_cache
             .hashmap
             .borrow()
-            .get(&trait_ref)
+            .get(&param_env.and(trait_ref))
             .map(|v| v.get(tcx))
     }
 
@@ -1182,7 +1187,7 @@
                     .evaluation_cache
                     .hashmap
                     .borrow_mut()
-                    .insert(trait_ref, WithDepNode::new(dep_node, result));
+                    .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
                 return;
             }
         }
@@ -1195,7 +1200,7 @@
             .evaluation_cache
             .hashmap
             .borrow_mut()
-            .insert(trait_ref, WithDepNode::new(dep_node, result));
+            .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
     }
 
     /// For various reasons, it's possible for a subobligation
@@ -1567,14 +1572,10 @@
     /// Do note that if the type itself is not in the
     /// global tcx, the local caches will be used.
     fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
-        // If there are any where-clauses in scope, then we always use
-        // a cache local to this particular scope. Otherwise, we
-        // switch to a global cache. We used to try and draw
-        // finer-grained distinctions, but that led to a serious of
-        // annoying and weird bugs like #22019 and #18290. This simple
-        // rule seems to be pretty clearly safe and also still retains
-        // a very high hit rate (~95% when compiling rustc).
-        if !param_env.caller_bounds.is_empty() {
+        // If there are any e.g. inference variables in the `ParamEnv`, then we
+        // always use a cache local to this particular scope. Otherwise, we
+        // switch to a global cache.
+        if param_env.has_local_value() {
             return false;
         }
 
@@ -1602,7 +1603,7 @@
         let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref;
         if self.can_use_global_caches(param_env) {
             let cache = tcx.selection_cache.hashmap.borrow();
-            if let Some(cached) = cache.get(&trait_ref) {
+            if let Some(cached) = cache.get(&param_env.and(*trait_ref)) {
                 return Some(cached.get(tcx));
             }
         }
@@ -1610,7 +1611,7 @@
             .selection_cache
             .hashmap
             .borrow()
-            .get(trait_ref)
+            .get(&param_env.and(*trait_ref))
             .map(|v| v.get(tcx))
     }
 
@@ -1671,7 +1672,7 @@
                     tcx.selection_cache
                         .hashmap
                         .borrow_mut()
-                        .insert(trait_ref, WithDepNode::new(dep_node, candidate));
+                        .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
                     return;
                 }
             }
@@ -1685,7 +1686,7 @@
             .selection_cache
             .hashmap
             .borrow_mut()
-            .insert(trait_ref, WithDepNode::new(dep_node, candidate));
+            .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
     }
 
     fn assemble_candidates<'o>(
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 6a0002c..f7e422b 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -8,6 +8,7 @@
 use crate::session::config::{BorrowckMode, OutputFilenames};
 use crate::session::config::CrateType;
 use crate::middle;
+use crate::middle::lang_items::PanicLocationLangItem;
 use crate::hir::{self, TraitCandidate, HirId, ItemKind, ItemLocalId, Node};
 use crate::hir::def::{Res, DefKind, Export};
 use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
@@ -22,7 +23,7 @@
 use crate::middle::lang_items;
 use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use crate::middle::stability;
-use crate::mir::{BodyCache, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted};
+use crate::mir::{BodyAndCache, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted};
 use crate::mir::interpret::{ConstValue, Allocation, Scalar};
 use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst};
 use crate::ty::ReprOptions;
@@ -1083,17 +1084,17 @@
         &self.hir_map
     }
 
-    pub fn alloc_steal_mir(self, mir: BodyCache<'tcx>) -> &'tcx Steal<BodyCache<'tcx>> {
+    pub fn alloc_steal_mir(self, mir: BodyAndCache<'tcx>) -> &'tcx Steal<BodyAndCache<'tcx>> {
         self.arena.alloc(Steal::new(mir))
     }
 
-    pub fn alloc_steal_promoted(self, promoted: IndexVec<Promoted, BodyCache<'tcx>>) ->
-        &'tcx Steal<IndexVec<Promoted, BodyCache<'tcx>>> {
+    pub fn alloc_steal_promoted(self, promoted: IndexVec<Promoted, BodyAndCache<'tcx>>) ->
+        &'tcx Steal<IndexVec<Promoted, BodyAndCache<'tcx>>> {
         self.arena.alloc(Steal::new(promoted))
     }
 
-    pub fn intern_promoted(self, promoted: IndexVec<Promoted, BodyCache<'tcx>>) ->
-        &'tcx IndexVec<Promoted, BodyCache<'tcx>> {
+    pub fn intern_promoted(self, promoted: IndexVec<Promoted, BodyAndCache<'tcx>>) ->
+        &'tcx IndexVec<Promoted, BodyAndCache<'tcx>> {
         self.arena.alloc(promoted)
     }
 
@@ -1588,6 +1589,15 @@
     pub fn has_strict_asm_symbol_naming(&self) -> bool {
         self.sess.target.target.arch.contains("nvptx")
     }
+
+    /// Returns `&'static core::panic::Location<'static>`.
+    pub fn caller_location_ty(&self) -> Ty<'tcx> {
+        self.mk_imm_ref(
+            self.lifetimes.re_static,
+            self.type_of(self.require_lang_item(PanicLocationLangItem, None))
+                .subst(*self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
+        )
+    }
 }
 
 impl<'tcx> GlobalCtxt<'tcx> {
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 801dfa8..366951b 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -116,6 +116,10 @@
         }
         tcx.codegen_fn_attrs(self.def_id()).requests_inline()
     }
+
+    pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
+        tcx.codegen_fn_attrs(self.def_id()).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
+    }
 }
 
 impl<'tcx> fmt::Display for Instance<'tcx> {
@@ -255,11 +259,8 @@
     ) -> Option<Instance<'tcx>> {
         debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
         Instance::resolve(tcx, param_env, def_id, substs).map(|mut resolved| {
-            let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags
-                .contains(CodegenFnAttrFlags::TRACK_CALLER);
-
             match resolved.def {
-                InstanceDef::Item(def_id) if has_track_caller(def_id) => {
+                InstanceDef::Item(def_id) if resolved.def.requires_caller_location(tcx) => {
                     debug!(" => fn pointer created for function with #[track_caller]");
                     resolved.def = InstanceDef::ReifyShim(def_id);
                 }
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 7f93e8c..c7278dc 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -2434,6 +2434,7 @@
         cx: &C,
         sig: ty::PolyFnSig<'tcx>,
         extra_args: &[Ty<'tcx>],
+        caller_location: Option<Ty<'tcx>>,
         mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
     ) -> Self;
     fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
@@ -2448,13 +2449,19 @@
         + HasParamEnv<'tcx>,
 {
     fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
-        call::FnAbi::new_internal(cx, sig, extra_args, |ty, _| ArgAbi::new(cx.layout_of(ty)))
+        call::FnAbi::new_internal(cx, sig, extra_args, None, |ty, _| ArgAbi::new(cx.layout_of(ty)))
     }
 
     fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
         let sig = instance.fn_sig_for_fn_abi(cx.tcx());
 
-        call::FnAbi::new_internal(cx, sig, extra_args, |ty, arg_idx| {
+        let caller_location = if instance.def.requires_caller_location(cx.tcx()) {
+            Some(cx.tcx().caller_location_ty())
+        } else {
+            None
+        };
+
+        call::FnAbi::new_internal(cx, sig, extra_args, caller_location, |ty, arg_idx| {
             let mut layout = cx.layout_of(ty);
             // Don't pass the vtable, it's not an argument of the virtual fn.
             // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -2479,7 +2486,7 @@
                     'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
                         && !fat_pointer_layout.ty.is_region_ptr()
                     {
-                        'iter_fields: for i in 0..fat_pointer_layout.fields.count() {
+                        for i in 0..fat_pointer_layout.fields.count() {
                             let field_layout = fat_pointer_layout.field(cx, i);
 
                             if !field_layout.is_zst() {
@@ -2512,6 +2519,7 @@
         cx: &C,
         sig: ty::PolyFnSig<'tcx>,
         extra_args: &[Ty<'tcx>],
+        caller_location: Option<Ty<'tcx>>,
         mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
     ) -> Self {
         debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args);
@@ -2684,6 +2692,7 @@
                 .iter()
                 .cloned()
                 .chain(extra_args)
+                .chain(caller_location)
                 .enumerate()
                 .map(|(i, ty)| arg_of(ty, Some(i)))
                 .collect(),
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index c9a934e..78a31f4 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -18,7 +18,7 @@
 use crate::middle::cstore::CrateStoreDyn;
 use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
-use crate::mir::ReadOnlyBodyCache;
+use crate::mir::ReadOnlyBodyAndCache;
 use crate::mir::interpret::{GlobalId, ErrorHandled};
 use crate::mir::GeneratorLayout;
 use crate::session::CrateDisambiguator;
@@ -2784,11 +2784,7 @@
             }
         };
 
-        if is_associated_item {
-            Some(self.associated_item(def_id))
-        } else {
-            None
-        }
+        is_associated_item.then(|| self.associated_item(def_id))
     }
 
     fn associated_item_from_trait_item_ref(self,
@@ -2985,7 +2981,7 @@
     }
 
     /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
-    pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> ReadOnlyBodyCache<'tcx, 'tcx> {
+    pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> ReadOnlyBodyAndCache<'tcx, 'tcx> {
         match instance {
             ty::InstanceDef::Item(did) => {
                 self.optimized_mir(did).unwrap_read_only()
@@ -3253,7 +3249,7 @@
     let unnormalized_env = ty::ParamEnv::new(
         tcx.intern_predicates(&predicates),
         traits::Reveal::UserFacing,
-        if tcx.sess.opts.debugging_opts.chalk { Some(def_id) } else { None }
+        tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
     );
 
     let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index fff2f06..745f7d0 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -1282,6 +1282,9 @@
             if !self.empty_path {
                 write!(self, "::")?;
             }
+            if ast::Ident::from_str(&name).is_raw_guess() {
+                write!(self, "r#")?;
+            }
             write!(self, "{}", name)?;
 
             // FIXME(eddyb) this will print e.g. `{{closure}}#3`, but it
diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs
index e5f4e79..2f30b79 100644
--- a/src/librustc/ty/query/job.rs
+++ b/src/librustc/ty/query/job.rs
@@ -303,13 +303,8 @@
         return true;
     }
 
-    visit_waiters(query, |_, successor| {
-        if connected_to_root(successor, visited) {
-            Some(None)
-        } else {
-            None
-        }
-    }).is_some()
+    visit_waiters(query, |_, successor| connected_to_root(successor, visited).then_some(None))
+        .is_some()
 }
 
 // Deterministically pick an query from a list
diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml
index 867bbd2..71cfacf 100644
--- a/src/librustc_codegen_llvm/Cargo.toml
+++ b/src/librustc_codegen_llvm/Cargo.toml
@@ -7,8 +7,28 @@
 [lib]
 name = "rustc_codegen_llvm"
 path = "lib.rs"
-crate-type = ["dylib"]
 test = false
+doctest = false
 
 [dependencies]
+bitflags = "1.0"
+flate2 = "1.0"
+libc = "0.2"
+log = "0.4"
+rustc = { path = "../librustc" }
+rustc-demangle = "0.1"
+rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }
+rustc_codegen_utils = { path = "../librustc_codegen_utils" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_feature = { path = "../librustc_feature" }
+rustc_fs_util = { path = "../librustc_fs_util" }
+rustc_incremental = { path = "../librustc_incremental" }
+rustc_index = { path = "../librustc_index" }
 rustc_llvm = { path = "../librustc_llvm" }
+rustc_session = { path = "../librustc_session" }
+rustc_target = { path = "../librustc_target" }
+smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
+syntax = { path = "../libsyntax" }
+syntax_expand = { path = "../libsyntax_expand" }
+syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 1f3c8e1..2607a49 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -8,6 +8,7 @@
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::mir::operand::OperandValue;
+use rustc::bug;
 use rustc_codegen_ssa::traits::*;
 use rustc_target::abi::call::ArgAbi;
 use rustc_target::abi::{HasDataLayout, LayoutOf};
diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs
index 11b6e0b..e1d56b9 100644
--- a/src/librustc_codegen_llvm/allocator.rs
+++ b/src/librustc_codegen_llvm/allocator.rs
@@ -4,6 +4,7 @@
 use libc::c_uint;
 use rustc::ty::TyCtxt;
 use syntax::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
+use rustc::bug;
 
 use crate::ModuleLlvm;
 use crate::llvm::{self, False, True};
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index abdd2e3..fa43e08 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -12,7 +12,7 @@
 
 use std::ffi::{CStr, CString};
 use libc::{c_uint, c_char};
-
+use log::debug;
 
 impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn codegen_inline_asm(
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 33dc251..5479a1f 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -12,6 +12,7 @@
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_target::abi::call::Conv;
+use rustc_data_structures::const_cstr;
 use rustc_target::spec::PanicStrategy;
 use rustc_codegen_ssa::traits::*;
 
@@ -375,11 +376,7 @@
         let native_libs = tcx.native_libraries(cnum);
 
         let def_id_to_native_lib = native_libs.iter().filter_map(|lib|
-            if let Some(id) = lib.foreign_module {
-                Some((id, lib))
-            } else {
-                None
-            }
+            lib.foreign_module.map(|id| (id, lib))
         ).collect::<FxHashMap<_, _>>();
 
         let mut ret = FxHashMap::default();
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 858dd59..0e4e4e2 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -4,11 +4,12 @@
 use crate::llvm::archive_ro::ArchiveRO;
 use crate::llvm::{self, True, False};
 use crate::{ModuleLlvm, LlvmCodegenBackend};
+use rustc::bug;
 use rustc_codegen_ssa::back::symbol_export;
 use rustc_codegen_ssa::back::write::{ModuleConfig, CodegenContext, FatLTOInput};
 use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinShared, ThinModule};
 use rustc_codegen_ssa::traits::*;
-use errors::{FatalError, Handler};
+use rustc_errors::{FatalError, Handler};
 use rustc::dep_graph::WorkProduct;
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc::hir::def_id::LOCAL_CRATE;
@@ -17,6 +18,7 @@
 use rustc::util::common::time_ext;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_codegen_ssa::{RLIB_BYTECODE_EXTENSION, ModuleCodegen, ModuleKind};
+use log::{info, debug};
 
 use std::ffi::{CStr, CString};
 use std::ptr;
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 48bbc13..796ea7a 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -10,6 +10,7 @@
 use crate::context::{is_pie_binary, get_reloc_model};
 use crate::common;
 use crate::LlvmCodegenBackend;
+use rustc::bug;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler};
 use rustc_codegen_ssa::traits::*;
@@ -20,9 +21,10 @@
 use rustc::util::common::time_ext;
 use rustc_fs_util::{path_to_c_string, link_or_copy};
 use rustc_data_structures::small_c_str::SmallCStr;
-use errors::{Handler, FatalError};
+use rustc_errors::{Handler, FatalError};
+use log::debug;
 
-use std::ffi::{CString, CStr};
+use std::ffi::CString;
 use std::fs;
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
@@ -55,7 +57,7 @@
     ("local-exec", llvm::ThreadLocalMode::LocalExec),
 ];
 
-pub fn llvm_err(handler: &errors::Handler, msg: &str) -> FatalError {
+pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError {
     match llvm::last_error() {
         Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
         None => handler.fatal(&msg),
@@ -63,7 +65,7 @@
 }
 
 pub fn write_output_file(
-        handler: &errors::Handler,
+        handler: &rustc_errors::Handler,
         target: &'ll llvm::TargetMachine,
         pm: &llvm::PassManager<'ll>,
         m: &'ll llvm::Module,
@@ -588,14 +590,11 @@
                     cursor.position() as size_t
                 }
 
-                with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                    let result =
-                        llvm::LLVMRustPrintModule(cpm, llmod, out_c.as_ptr(), demangle_callback);
-                    llvm::LLVMDisposePassManager(cpm);
-                    result.into_result().map_err(|()| {
-                        let msg = format!("failed to write LLVM IR to {}", out.display());
-                        llvm_err(diag_handler, &msg)
-                    })
+                let result =
+                    llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
+                result.into_result().map_err(|()| {
+                    let msg = format!("failed to write LLVM IR to {}", out.display());
+                    llvm_err(diag_handler, &msg)
                 })?;
             }
 
@@ -836,8 +835,8 @@
             })
             .filter_map(|val| {
                 // Exclude some symbols that we know are not Rust symbols.
-                let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
-                if ignored(name.to_bytes()) {
+                let name = llvm::get_value_name(val);
+                if ignored(name) {
                     None
                 } else {
                     Some((val, name))
@@ -845,7 +844,7 @@
             })
             .map(move |(val, name)| {
                 let mut imp_name = prefix.as_bytes().to_vec();
-                imp_name.extend(name.to_bytes());
+                imp_name.extend(name);
                 let imp_name = CString::new(imp_name).unwrap();
                 (imp_name, val)
             })
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 6f72466..7509584 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -23,6 +23,8 @@
 use std::ops::{Deref, Range};
 use std::ptr;
 use std::iter::TrustedLen;
+use rustc_data_structures::const_cstr;
+use log::debug;
 
 // All Builders must have an llfn associated with them
 #[must_use]
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index e0db7ca..c0be87b 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -10,6 +10,7 @@
 use crate::context::CodegenCx;
 use crate::value::Value;
 use rustc_codegen_ssa::traits::*;
+use log::debug;
 
 use rustc::ty::{TypeFoldable, Instance};
 use rustc::ty::layout::{FnAbiExt, HasTyCtxt};
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index f38f9df..ff03c1f 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -8,6 +8,8 @@
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 use rustc_codegen_ssa::traits::*;
+use rustc::bug;
+use log::debug;
 
 use crate::consts::const_alloc_to_llvm;
 use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size};
@@ -245,11 +247,7 @@
             let (mut lo, mut hi) = (0u64, 0u64);
             let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
                                                         &mut hi, &mut lo);
-            if success {
-                Some(hi_lo_to_u128(lo, hi))
-            } else {
-                None
-            }
+            success.then_some(hi_lo_to_u128(lo, hi))
         })
     }
 
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 541b3d9..11a105c 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -16,12 +16,14 @@
 use rustc_codegen_ssa::traits::*;
 use syntax::symbol::{Symbol, sym};
 use syntax_pos::Span;
+use rustc::{bug, span_bug};
+use log::debug;
 
 use rustc::ty::layout::{self, Size, Align, LayoutOf};
 
 use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags};
 
-use std::ffi::{CStr, CString};
+use std::ffi::CStr;
 
 pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
     let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1);
@@ -392,16 +394,14 @@
             } else {
                 // If we created the global with the wrong type,
                 // correct the type.
-                let empty_string = const_cstr!("");
-                let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g));
-                let name_string = CString::new(name_str_ref.to_bytes()).unwrap();
-                llvm::LLVMSetValueName(g, empty_string.as_ptr());
+                let name = llvm::get_value_name(g).to_vec();
+                llvm::set_value_name(g, b"");
 
                 let linkage = llvm::LLVMRustGetLinkage(g);
                 let visibility = llvm::LLVMRustGetVisibility(g);
 
                 let new_g = llvm::LLVMRustGetOrInsertGlobal(
-                    self.llmod, name_string.as_ptr(), val_llty);
+                    self.llmod, name.as_ptr().cast(), name.len(), val_llty);
 
                 llvm::LLVMRustSetLinkage(new_g, linkage);
                 llvm::LLVMRustSetVisibility(new_g, visibility);
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 39ea1f6..2c894a5 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -12,6 +12,7 @@
 
 use rustc_data_structures::base_n;
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc::bug;
 use rustc::mir::mono::CodegenUnit;
 use rustc::session::config::{self, DebugInfo};
 use rustc::session::Session;
@@ -23,6 +24,7 @@
 use rustc_target::spec::{HasTargetSpec, Target};
 use rustc_codegen_ssa::base::wants_msvc_seh;
 use crate::callee::get_fn;
+use rustc_data_structures::const_cstr;
 
 use std::ffi::CStr;
 use std::cell::{Cell, RefCell};
diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs
index 9ed1c17..739437a 100644
--- a/src/librustc_codegen_llvm/debuginfo/gdb.rs
+++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs
@@ -7,6 +7,7 @@
 use crate::value::Value;
 use rustc::session::config::DebugInfo;
 use rustc_codegen_ssa::traits::*;
+use rustc::bug;
 
 use syntax::attr;
 use syntax::symbol::sym;
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 1847e4e..8327ff2 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -35,10 +35,13 @@
 use rustc::util::nodemap::FxHashMap;
 use rustc_fs_util::path_to_c_string;
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_data_structures::const_cstr;
 use rustc_target::abi::HasDataLayout;
 use syntax::ast;
 use syntax::symbol::{Interner, Symbol};
 use syntax_pos::{self, Span, FileName};
+use rustc::{bug, span_bug};
+use log::debug;
 
 use libc::{c_uint, c_longlong};
 use std::collections::hash_map::Entry;
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index c2359a2..1de298d 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -32,7 +32,8 @@
 
 use libc::c_uint;
 use std::cell::RefCell;
-use std::ffi::{CStr, CString};
+use std::ffi::CString;
+use log::debug;
 
 use smallvec::SmallVec;
 use syntax_pos::{self, BytePos, Span, Pos};
@@ -255,23 +256,11 @@
             return;
         }
 
-        let old_name = unsafe {
-            CStr::from_ptr(llvm::LLVMGetValueName(value))
-        };
-        match old_name.to_str() {
-            Ok("") => {}
-            Ok(_) => {
-                // Avoid replacing the name if it already exists.
-                // While we could combine the names somehow, it'd
-                // get noisy quick, and the usefulness is dubious.
-                return;
-            }
-            Err(_) => return,
-        }
-
-        let cname = SmallCStr::new(name);
-        unsafe {
-            llvm::LLVMSetValueName(value, cname.as_ptr());
+        // Avoid replacing the name if it already exists.
+        // While we could combine the names somehow, it'd
+        // get noisy quick, and the usefulness is dubious.
+        if llvm::get_value_name(value).is_empty() {
+            llvm::set_value_name(value, name.as_bytes());
         }
     }
 }
diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
index ccb3bde..82183fa 100644
--- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs
+++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
@@ -8,6 +8,7 @@
 use crate::llvm::debuginfo::DIScope;
 use crate::builder::Builder;
 use rustc_codegen_ssa::traits::*;
+use log::debug;
 
 use libc::c_uint;
 use syntax_pos::{Span, Pos};
diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs
index 8b6fedc..5144b92 100644
--- a/src/librustc_codegen_llvm/declare.rs
+++ b/src/librustc_codegen_llvm/declare.rs
@@ -22,6 +22,7 @@
 use rustc::session::config::Sanitizer;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_codegen_ssa::traits::*;
+use log::debug;
 
 /// Declare a function.
 ///
@@ -76,9 +77,8 @@
         name: &str, ty: &'ll Type
     ) -> &'ll Value {
         debug!("declare_global(name={:?})", name);
-        let namebuf = SmallCStr::new(name);
         unsafe {
-            llvm::LLVMRustGetOrInsertGlobal(self.llmod, namebuf.as_ptr(), ty)
+            llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty)
         }
     }
 
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 9df75a8..900f2d2 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -19,6 +19,7 @@
 use rustc::hir;
 use rustc_target::abi::HasDataLayout;
 use syntax::ast;
+use rustc::{bug, span_bug};
 
 use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
 use rustc_codegen_ssa::traits::*;
@@ -516,9 +517,36 @@
                         return;
                     }
                 }
-
             },
 
+            "float_to_int_approx_unchecked" => {
+                if float_type_width(arg_tys[0]).is_none() {
+                    span_invalid_monomorphization_error(
+                        tcx.sess, span,
+                        &format!("invalid monomorphization of `float_to_int_approx_unchecked` \
+                                  intrinsic: expected basic float type, \
+                                  found `{}`", arg_tys[0]));
+                    return;
+                }
+                match int_type_width_signed(ret_ty, self.cx) {
+                    Some((width, signed)) => {
+                        if signed {
+                            self.fptosi(args[0].immediate(), self.cx.type_ix(width))
+                        } else {
+                            self.fptoui(args[0].immediate(), self.cx.type_ix(width))
+                        }
+                    }
+                    None => {
+                        span_invalid_monomorphization_error(
+                            tcx.sess, span,
+                            &format!("invalid monomorphization of `float_to_int_approx_unchecked` \
+                                      intrinsic:  expected basic integer type, \
+                                      found `{}`", ret_ty));
+                        return;
+                    }
+                }
+            }
+
             "discriminant_value" => {
                 args[0].deref(self.cx()).codegen_get_discr(self, ret_ty)
             }
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 2ff5872..1e1d74c 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -6,6 +6,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(const_cstr_unchecked)]
@@ -23,33 +24,11 @@
 use back::write::{create_target_machine, create_informational_target_machine};
 use syntax_pos::symbol::Symbol;
 
-extern crate rustc_demangle;
-extern crate flate2;
-#[macro_use] extern crate bitflags;
-extern crate libc;
-#[macro_use] extern crate rustc;
-extern crate rustc_target;
-#[macro_use] extern crate rustc_data_structures;
-extern crate rustc_feature;
-extern crate rustc_index;
-extern crate rustc_incremental;
-extern crate rustc_codegen_utils;
-extern crate rustc_codegen_ssa;
-extern crate rustc_fs_util;
-extern crate rustc_driver as _;
-
-#[macro_use] extern crate log;
-extern crate smallvec;
-extern crate syntax;
-extern crate syntax_pos;
-extern crate rustc_errors as errors;
-extern crate rustc_session;
-
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, FatLTOInput};
 use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModule};
 use rustc_codegen_ssa::CompiledModule;
-use errors::{FatalError, Handler};
+use rustc_errors::{FatalError, Handler};
 use rustc::dep_graph::WorkProduct;
 use syntax::expand::allocator::AllocatorKind;
 pub use llvm_util::target_features;
@@ -338,12 +317,6 @@
     }
 }
 
-/// This is the entrypoint for a hot plugged rustc_codegen_llvm
-#[no_mangle]
-pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
-    LlvmCodegenBackend::new()
-}
-
 pub struct ModuleLlvm {
     llcx: &'static mut llvm::Context,
     llmod_raw: *const llvm::Module,
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index fd31e65..b8a1003 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -544,6 +544,7 @@
 
 pub mod debuginfo {
     use super::{InvariantOpaque, Metadata};
+    use bitflags::bitflags;
 
     #[repr(C)]
     pub struct DIBuilder<'a>(InvariantOpaque<'a>);
@@ -701,8 +702,8 @@
 
     // Operations on all values
     pub fn LLVMTypeOf(Val: &Value) -> &Type;
-    pub fn LLVMGetValueName(Val: &Value) -> *const c_char;
-    pub fn LLVMSetValueName(Val: &Value, Name: *const c_char);
+    pub fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
+    pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
     pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value);
     pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value);
 
@@ -774,7 +775,8 @@
     pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
     pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
     pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
-    pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, T: &'a Type) -> &'a Value;
+    pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, NameLen: size_t,
+                                     T: &'a Type) -> &'a Value;
     pub fn LLVMRustInsertPrivateGlobal(M: &'a Module, T: &'a Type) -> &'a Value;
     pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
     pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
@@ -1727,8 +1729,7 @@
                                    Output: *const c_char,
                                    FileType: FileType)
                                    -> LLVMRustResult;
-    pub fn LLVMRustPrintModule(PM: &PassManager<'a>,
-                               M: &'a Module,
+    pub fn LLVMRustPrintModule(M: &'a Module,
                                Output: *const c_char,
                                Demangle: extern fn(*const c_char,
                                                    size_t,
@@ -1812,7 +1813,7 @@
 
     pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock);
 
-    pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char);
+    pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t);
     pub fn LLVMRustUnsetComdat(V: &Value);
     pub fn LLVMRustSetModulePICLevel(M: &Module);
     pub fn LLVMRustSetModulePIELevel(M: &Module);
diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs
index 5781593..9757567 100644
--- a/src/librustc_codegen_llvm/llvm/mod.rs
+++ b/src/librustc_codegen_llvm/llvm/mod.rs
@@ -10,11 +10,11 @@
 
 use std::str::FromStr;
 use std::string::FromUtf8Error;
-use std::slice;
 use std::ffi::CStr;
 use std::cell::RefCell;
-use libc::{c_uint, c_char, size_t};
+use libc::c_uint;
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_llvm::RustString;
 
 pub mod archive_ro;
 pub mod diagnostic;
@@ -81,21 +81,6 @@
     }
 }
 
-#[repr(C)]
-pub struct RustString {
-    bytes: RefCell<Vec<u8>>,
-}
-
-/// Appending to a Rust string -- used by RawRustStringOstream.
-#[no_mangle]
-pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString,
-                                                 ptr: *const c_char,
-                                                 size: size_t) {
-    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
-
-    sr.bytes.borrow_mut().extend_from_slice(slice);
-}
-
 pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) {
     unsafe {
         LLVMSetInstructionCallConv(instr, cc as c_uint);
@@ -115,7 +100,8 @@
 // For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52
 pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
     unsafe {
-        LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
+        let name = get_value_name(val);
+        LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len());
     }
 }
 
@@ -217,6 +203,23 @@
     }
 }
 
+/// Safe wrapper for `LLVMGetValueName2` into a byte slice
+pub fn get_value_name(value: &'a Value) -> &'a [u8] {
+    unsafe {
+        let mut len = 0;
+        let data = LLVMGetValueName2(value, &mut len);
+        std::slice::from_raw_parts(data.cast(), len)
+    }
+}
+
+/// Safe wrapper for `LLVMSetValueName2` from a byte slice
+pub fn set_value_name(value: &Value, name: &[u8]) {
+    unsafe {
+        let data = name.as_ptr().cast();
+        LLVMSetValueName2(value, data, name.len());
+    }
+}
+
 pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
     let sr = RustString {
         bytes: RefCell::new(Vec::new()),
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 72612c4..4073938 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -8,6 +8,7 @@
 use std::ffi::CString;
 use rustc_feature::UnstableFeatures;
 use syntax::symbol::sym;
+use rustc::bug;
 
 use std::str;
 use std::slice;
diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs
index cd72558..bbe42e3 100644
--- a/src/librustc_codegen_llvm/metadata.rs
+++ b/src/librustc_codegen_llvm/metadata.rs
@@ -6,6 +6,8 @@
 
 use rustc_data_structures::owning_ref::OwningRef;
 use rustc_codegen_ssa::METADATA_FILENAME;
+use log::debug;
+use rustc_data_structures::rustc_erase_owner;
 
 use std::path::Path;
 use std::slice;
diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs
index cbc8af4..9f6bdd2 100644
--- a/src/librustc_codegen_llvm/mono_item.rs
+++ b/src/librustc_codegen_llvm/mono_item.rs
@@ -9,6 +9,7 @@
 use rustc::ty::{TypeFoldable, Instance};
 use rustc::ty::layout::{FnAbiExt, LayoutOf};
 use rustc_codegen_ssa::traits::*;
+use log::debug;
 
 pub use rustc::mir::mono::MonoItem;
 
diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs
index f936367..e6677f3 100644
--- a/src/librustc_codegen_llvm/type_.rs
+++ b/src/librustc_codegen_llvm/type_.rs
@@ -5,6 +5,7 @@
 use crate::context::CodegenCx;
 use crate::value::Value;
 use rustc_codegen_ssa::traits::*;
+use rustc::bug;
 
 use crate::common;
 use crate::type_of::LayoutLlvmExt;
diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs
index d77bbb2..f9cbf4b 100644
--- a/src/librustc_codegen_llvm/type_of.rs
+++ b/src/librustc_codegen_llvm/type_of.rs
@@ -6,6 +6,8 @@
 use rustc_target::abi::TyLayoutMethods;
 use rustc::ty::print::obsolete::DefPathBasedNames;
 use rustc_codegen_ssa::traits::*;
+use log::debug;
+use rustc::bug;
 
 use std::fmt::Write;
 
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index 53d3c51..d489852 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -13,7 +13,7 @@
 bitflags = "1.2.1"
 cc = "1.0.1"
 num_cpus = "1.0"
-memmap = "0.6"
+memmap = "0.7"
 log = "0.4.5"
 libc = "0.2.44"
 jobserver = "0.1.11"
diff --git a/src/librustc_codegen_ssa/back/rpath.rs b/src/librustc_codegen_ssa/back/rpath.rs
index e27cb6d..cd3d999 100644
--- a/src/librustc_codegen_ssa/back/rpath.rs
+++ b/src/librustc_codegen_ssa/back/rpath.rs
@@ -119,11 +119,7 @@
     use std::path::Component;
 
     if path.is_absolute() != base.is_absolute() {
-        if path.is_absolute() {
-            Some(PathBuf::from(path))
-        } else {
-            None
-        }
+        path.is_absolute().then(|| PathBuf::from(path))
     } else {
         let mut ita = path.components();
         let mut itb = base.components();
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index f8b3e0f..cea5dc1 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -85,11 +85,7 @@
             match tcx.hir().get(hir_id) {
                 Node::ForeignItem(..) => {
                     let def_id = tcx.hir().local_def_id(hir_id);
-                    if tcx.is_statically_included_foreign_item(def_id) {
-                        Some(def_id)
-                    } else {
-                        None
-                    }
+                    tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
                 }
 
                 // Only consider nodes that actually have exported symbols.
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 9784d87..9919666 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -1,5 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
@@ -68,22 +69,14 @@
                             emit_bc: bool,
                             emit_bc_compressed: bool,
                             outputs: &OutputFilenames) -> CompiledModule {
-        let object = if emit_obj {
-            Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
-        } else {
-            None
-        };
-        let bytecode = if emit_bc {
-            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
-        } else {
-            None
-        };
-        let bytecode_compressed = if emit_bc_compressed {
-            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
-                    .with_extension(RLIB_BYTECODE_EXTENSION))
-        } else {
-            None
-        };
+        let object = emit_obj
+            .then(|| outputs.temp_path(OutputType::Object, Some(&self.name)));
+        let bytecode = emit_bc
+            .then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name)));
+        let bytecode_compressed = emit_bc_compressed.then(|| {
+            outputs.temp_path(OutputType::Bitcode, Some(&self.name))
+                .with_extension(RLIB_BYTECODE_EXTENSION)
+        });
 
         CompiledModule {
             name: self.name.clone(),
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 6dccf32..dabd097 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -153,7 +153,7 @@
     // a loop.
     fn maybe_sideeffect<Bx: BuilderMethods<'a, 'tcx>>(
         &self,
-        mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>,
+        mir: mir::ReadOnlyBodyAndCache<'tcx, 'tcx>,
         bx: &mut Bx,
         targets: &[mir::BasicBlock],
     ) {
@@ -261,7 +261,11 @@
         if self.fn_abi.ret.layout.abi.is_uninhabited() {
             // Functions with uninhabited return values are marked `noreturn`,
             // so we should make sure that we never actually do.
+            // We play it safe by using a well-defined `abort`, but we could go for immediate UB
+            // if that turns out to be helpful.
             bx.abort();
+            // `abort` does not terminate the block, so we still need to generate
+            // an `unreachable` terminator after it.
             bx.unreachable();
             return;
         }
@@ -714,7 +718,7 @@
                     'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
                                     && !op.layout.ty.is_region_ptr()
                     {
-                        'iter_fields: for i in 0..op.layout.fields.count() {
+                        for i in 0..op.layout.fields.count() {
                             let field = op.extract_field(&mut bx, i);
                             if !field.layout.is_zst() {
                                 // we found the one non-zero-sized field that is allowed
@@ -770,6 +774,18 @@
                 &fn_abi.args[first_args.len()..])
         }
 
+        let needs_location =
+            instance.map_or(false, |i| i.def.requires_caller_location(self.cx.tcx()));
+        if needs_location {
+            assert_eq!(
+                fn_abi.args.len(), args.len() + 1,
+                "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
+            );
+            let location = self.get_caller_location(&mut bx, span);
+            let last_arg = fn_abi.args.last().unwrap();
+            self.codegen_argument(&mut bx, location, &mut llargs, last_arg);
+        }
+
         let fn_ptr = match (llfn, instance) {
             (Some(llfn), _) => llfn,
             (None, Some(instance)) => bx.get_fn_addr(instance),
@@ -825,6 +841,8 @@
 
             mir::TerminatorKind::Abort => {
                 bx.abort();
+                // `abort` does not terminate the block, so we still need to generate
+                // an `unreachable` terminator after it.
                 bx.unreachable();
             }
 
@@ -1004,14 +1022,16 @@
         bx: &mut Bx,
         span: Span,
     ) -> OperandRef<'tcx, Bx::Value> {
-        let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
-        let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo());
-        let const_loc = bx.tcx().const_caller_location((
-            Symbol::intern(&caller.file.name.to_string()),
-            caller.line as u32,
-            caller.col_display as u32 + 1,
-        ));
-        OperandRef::from_const(bx, const_loc)
+        self.caller_location.unwrap_or_else(|| {
+            let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
+            let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo());
+            let const_loc = bx.tcx().const_caller_location((
+                Symbol::intern(&caller.file.name.to_string()),
+                caller.line as u32,
+                caller.col_display as u32 + 1,
+            ));
+            OperandRef::from_const(bx, const_loc)
+        })
     }
 
     fn get_personality_slot(
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index 27891be6..fb8f504 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -16,6 +16,10 @@
         constant: &mir::Constant<'tcx>,
     ) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
         match constant.literal.val {
+            // Special case unevaluated statics, because statics have an identity and thus should
+            // use `get_static` to get at their id.
+            // FIXME(oli-obk): can we unify this somehow, maybe by making const eval of statics
+            // always produce `&STATIC`. This may also simplify how const eval works with statics.
             ty::ConstKind::Unevaluated(def_id, substs)
                 if self.cx.tcx().is_static(def_id) => {
                     assert!(substs.is_empty(), "we don't support generic statics yet");
@@ -46,7 +50,10 @@
                     instance,
                     promoted: None,
                 };
-                self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
+                self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid)).map_err(|err| {
+                    self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
+                    err
+                })
             },
             _ => Ok(self.monomorphize(&constant.literal)),
         }
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 3a157ca..e535aec 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -21,7 +21,7 @@
 pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
     instance: Instance<'tcx>,
 
-    mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>,
+    mir: mir::ReadOnlyBodyAndCache<'tcx, 'tcx>,
 
     debug_context: Option<FunctionDebugContext<Bx::DIScope>>,
 
@@ -77,6 +77,9 @@
     /// All `VarDebuginfo` from the MIR body, partitioned by `Local`.
     /// This is `None` if no variable debuginfo/names are needed.
     per_local_var_debug_info: Option<IndexVec<mir::Local, Vec<&'tcx mir::VarDebugInfo<'tcx>>>>,
+
+    /// Caller location propagated if this function has `#[track_caller]`.
+    caller_location: Option<OperandRef<'tcx, Bx::Value>>,
 }
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
@@ -156,7 +159,7 @@
         }).collect();
 
     let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs);
-    let mir_body: &mir::Body<'_> = mir.body();
+    let mir_body: &mir::Body<'_> = *mir;
     let mut fx = FunctionCx {
         instance,
         mir,
@@ -172,13 +175,14 @@
         locals: IndexVec::new(),
         debug_context,
         per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir_body),
+        caller_location: None,
     };
 
     let memory_locals = analyze::non_ssa_locals(&fx);
 
     // Allocate variable and temp allocas
     fx.locals = {
-        let args = arg_local_refs(&mut bx, &fx, &memory_locals);
+        let args = arg_local_refs(&mut bx, &mut fx, &memory_locals);
 
         let mut allocate_local = |local| {
             let decl = &mir_body.local_decls[local];
@@ -320,14 +324,14 @@
 /// indirect.
 fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     bx: &mut Bx,
-    fx: &FunctionCx<'a, 'tcx, Bx>,
+    fx: &mut FunctionCx<'a, 'tcx, Bx>,
     memory_locals: &BitSet<mir::Local>,
 ) -> Vec<LocalRef<'tcx, Bx::Value>> {
     let mir = fx.mir;
     let mut idx = 0;
     let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize;
 
-    mir.args_iter().enumerate().map(|(arg_index, local)| {
+    let args = mir.args_iter().enumerate().map(|(arg_index, local)| {
         let arg_decl = &mir.local_decls[local];
 
         if Some(local) == mir.spread_arg {
@@ -423,7 +427,27 @@
             bx.store_fn_arg(arg, &mut llarg_idx, tmp);
             LocalRef::Place(tmp)
         }
-    }).collect()
+    }).collect::<Vec<_>>();
+
+    if fx.instance.def.requires_caller_location(bx.tcx()) {
+        assert_eq!(
+            fx.fn_abi.args.len(), args.len() + 1,
+            "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
+        );
+
+        let arg = fx.fn_abi.args.last().unwrap();
+        match arg.mode {
+            PassMode::Direct(_) => (),
+            _ => bug!("caller location must be PassMode::Direct, found {:?}", arg.mode),
+        }
+
+        fx.caller_location = Some(OperandRef {
+            val: OperandValue::Immediate(bx.get_param(llarg_idx)),
+            layout: arg.layout,
+        });
+    }
+
+    args
 }
 
 mod analyze;
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 310b8ae..a6dec81 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -475,9 +475,10 @@
                             },
                         }
                         // Allow RalfJ to sleep soundly knowing that even refactorings that remove
-                        // the above error (or silence it under some conditions) will not cause UB
+                        // the above error (or silence it under some conditions) will not cause UB.
                         bx.abort();
-                        // We've errored, so we don't have to produce working code.
+                        // We still have to return an operand but it doesn't matter,
+                        // this code is unreachable.
                         let ty = self.monomorphize(&constant.literal.ty);
                         let layout = bx.cx().layout_of(ty);
                         bx.load_operand(PlaceRef::new_sized(
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index e250739..5e13cab 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -333,6 +333,9 @@
         variant_index: VariantIdx
     ) {
         if self.layout.for_variant(bx.cx(), variant_index).abi.is_uninhabited() {
+            // We play it safe by using a well-defined `abort`, but we could go for immediate UB
+            // if that turns out to be helpful.
+            bx.abort();
             return;
         }
         match self.layout.variants {
@@ -488,10 +491,12 @@
                     },
                     Err(_) => {
                         // This is unreachable as long as runtime
-                        // and compile-time agree on values
+                        // and compile-time agree perfectly.
                         // With floats that won't always be true,
-                        // so we generate an abort.
+                        // so we generate a (safe) abort.
                         bx.abort();
+                        // We still have to return a place but it doesn't matter,
+                        // this code is unreachable.
                         let llval = bx.cx().const_undef(
                             bx.cx().type_ptr_to(bx.cx().backend_type(layout))
                         );
@@ -560,7 +565,7 @@
                         let llindex = bx.sub(lllen, lloffset);
                         cg_base.project_index(bx, llindex)
                     }
-                    mir::ProjectionElem::Subslice { from, to } => {
+                    mir::ProjectionElem::Subslice { from, to, from_end } => {
                         let mut subslice = cg_base.project_index(bx,
                             bx.cx().const_usize(*from as u64));
                         let projected_ty = PlaceTy::from_ty(cg_base.layout.ty)
@@ -568,6 +573,7 @@
                         subslice.layout = bx.cx().layout_of(self.monomorphize(&projected_ty));
 
                         if subslice.layout.is_unsized() {
+                            assert!(from_end, "slice subslices should be `from_end`");
                             subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(),
                                 bx.cx().const_usize((*from as u64) + (*to as u64))));
                         }
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 0fd4711..7fa40b8 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -26,7 +26,7 @@
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_index = { path = "../librustc_index", package = "rustc_index" }
 bitflags = "1.2.1"
-measureme = "0.4"
+measureme = "0.5"
 
 [dependencies.parking_lot]
 version = "0.9"
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 8a5badd..b1931ca 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -128,21 +128,19 @@
     ::std::iter::Map<::std::ops::RangeFrom<usize>, fn(usize) -> ObligationTreeId>;
 
 pub struct ObligationForest<O: ForestObligation> {
-    /// The list of obligations. In between calls to
-    /// `process_obligations`, this list only contains nodes in the
-    /// `Pending` or `Success` state (with a non-zero number of
-    /// incomplete children). During processing, some of those nodes
-    /// may be changed to the error state, or we may find that they
-    /// are completed (That is, `num_incomplete_children` drops to 0).
-    /// At the end of processing, those nodes will be removed by a
-    /// call to `compress`.
+    /// The list of obligations. In between calls to `process_obligations`,
+    /// this list only contains nodes in the `Pending` or `Success` state.
     ///
     /// `usize` indices are used here and throughout this module, rather than
-    /// `rustc_index::newtype_index!` indices, because this code is hot enough that the
-    /// `u32`-to-`usize` conversions that would be required are significant,
-    /// and space considerations are not important.
+    /// `rustc_index::newtype_index!` indices, because this code is hot enough
+    /// that the `u32`-to-`usize` conversions that would be required are
+    /// significant, and space considerations are not important.
     nodes: Vec<Node<O>>,
 
+    /// The process generation is 1 on the first call to `process_obligations`,
+    /// 2 on the second call, etc.
+    gen: u32,
+
     /// A cache of predicates that have been successfully completed.
     done_cache: FxHashSet<O::Predicate>,
 
@@ -211,31 +209,61 @@
 /// represents the current state of processing for the obligation (of
 /// type `O`) associated with this node.
 ///
-/// Outside of ObligationForest methods, nodes should be either Pending
-/// or Waiting.
+/// The non-`Error` state transitions are as follows.
+/// ```
+/// (Pre-creation)
+///  |
+///  |     register_obligation_at() (called by process_obligations() and
+///  v                               from outside the crate)
+/// Pending
+///  |
+///  |     process_obligations()
+///  v
+/// Success(not_waiting())
+///  |  |
+///  |  |  mark_still_waiting_nodes()
+///  |  v
+///  | Success(still_waiting())
+///  |  |
+///  |  |  compress()
+///  v  v
+/// (Removed)
+/// ```
+/// The `Error` state can be introduced in several places, via `error_at()`.
+///
+/// Outside of `ObligationForest` methods, nodes should be either `Pending` or
+/// `Success`.
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 enum NodeState {
-    /// Obligations for which selection had not yet returned a
-    /// non-ambiguous result.
+    /// This obligation has not yet been selected successfully. Cannot have
+    /// subobligations.
     Pending,
 
-    /// This obligation was selected successfully, but may or
-    /// may not have subobligations.
-    Success,
+    /// This obligation was selected successfully, but it may be waiting on one
+    /// or more pending subobligations, as indicated by the `WaitingState`.
+    Success(WaitingState),
 
-    /// This obligation was selected successfully, but it has
-    /// a pending subobligation.
-    Waiting,
-
-    /// This obligation, along with its subobligations, are complete,
-    /// and will be removed in the next collection.
-    Done,
-
-    /// This obligation was resolved to an error. Error nodes are
-    /// removed from the vector by the compression step.
+    /// This obligation was resolved to an error. It will be removed by the
+    /// next compression step.
     Error,
 }
 
+/// Indicates when a `Success` node was last (if ever) waiting on one or more
+/// `Pending` nodes. The notion of "when" comes from `ObligationForest::gen`.
+/// - 0: "Not waiting". This is a special value, set by `process_obligation`,
+///   and usable because generation counting starts at 1.
+/// - 1..ObligationForest::gen: "Was waiting" in a previous generation, but
+///   waiting no longer. In other words, finished.
+/// - ObligationForest::gen: "Still waiting" in this generation.
+///
+/// Things to note about this encoding:
+/// - Every time `ObligationForest::gen` is incremented, all the "still
+///   waiting" nodes automatically become "was waiting".
+/// - `ObligationForest::is_still_waiting` is very cheap.
+///
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
+struct WaitingState(u32);
+
 #[derive(Debug)]
 pub struct Outcome<O, E> {
     /// Obligations that were completely evaluated, including all
@@ -272,6 +300,7 @@
     pub fn new() -> ObligationForest<O> {
         ObligationForest {
             nodes: vec![],
+            gen: 0,
             done_cache: Default::default(),
             active_cache: Default::default(),
             node_rewrites: RefCell::new(vec![]),
@@ -300,10 +329,7 @@
 
         match self.active_cache.entry(obligation.as_predicate().clone()) {
             Entry::Occupied(o) => {
-                let index = *o.get();
-                debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!",
-                       obligation, parent, index);
-                let node = &mut self.nodes[index];
+                let node = &mut self.nodes[*o.get()];
                 if let Some(parent_index) = parent {
                     // If the node is already in `active_cache`, it has already
                     // had its chance to be marked with a parent. So if it's
@@ -320,9 +346,6 @@
                 }
             }
             Entry::Vacant(v) => {
-                debug!("register_obligation_at({:?}, {:?}) - ok, new index is {}",
-                       obligation, parent, self.nodes.len());
-
                 let obligation_tree_id = match parent {
                     Some(parent_index) => self.nodes[parent_index].obligation_tree_id,
                     None => self.obligation_tree_id_generator.next().unwrap(),
@@ -382,6 +405,18 @@
             .insert(node.obligation.as_predicate().clone());
     }
 
+    fn not_waiting() -> WaitingState {
+        WaitingState(0)
+    }
+
+    fn still_waiting(&self) -> WaitingState {
+        WaitingState(self.gen)
+    }
+
+    fn is_still_waiting(&self, waiting: WaitingState) -> bool {
+        waiting.0 == self.gen
+    }
+
     /// Performs a pass through the obligation list. This must
     /// be called in a loop until `outcome.stalled` is false.
     ///
@@ -390,7 +425,7 @@
                                   -> Outcome<O, P::Error>
         where P: ObligationProcessor<Obligation=O>
     {
-        debug!("process_obligations(len={})", self.nodes.len());
+        self.gen += 1;
 
         let mut errors = vec![];
         let mut stalled = true;
@@ -407,8 +442,6 @@
         while index < self.nodes.len() {
             let node = &mut self.nodes[index];
 
-            debug!("process_obligations: node {} == {:?}", index, node);
-
             // `processor.process_obligation` can modify the predicate within
             // `node.obligation`, and that predicate is the key used for
             // `self.active_cache`. This means that `self.active_cache` can get
@@ -418,18 +451,15 @@
                 index += 1;
                 continue;
             }
-            let result = processor.process_obligation(&mut node.obligation);
 
-            debug!("process_obligations: node {} got result {:?}", index, result);
-
-            match result {
+            match processor.process_obligation(&mut node.obligation) {
                 ProcessResult::Unchanged => {
                     // No change in state.
                 }
                 ProcessResult::Changed(children) => {
                     // We are not (yet) stalled.
                     stalled = false;
-                    node.state.set(NodeState::Success);
+                    node.state.set(NodeState::Success(Self::not_waiting()));
 
                     for child in children {
                         let st = self.register_obligation_at(
@@ -464,12 +494,10 @@
             };
         }
 
-        self.mark_as_waiting();
+        self.mark_still_waiting_nodes();
         self.process_cycles(processor);
         let completed = self.compress(do_completed);
 
-        debug!("process_obligations: complete");
-
         Outcome {
             completed,
             errors,
@@ -477,56 +505,6 @@
         }
     }
 
-    /// Mark all `NodeState::Success` nodes as `NodeState::Done` and
-    /// report all cycles between them. This should be called
-    /// after `mark_as_waiting` marks all nodes with pending
-    /// subobligations as NodeState::Waiting.
-    fn process_cycles<P>(&self, processor: &mut P)
-        where P: ObligationProcessor<Obligation=O>
-    {
-        let mut stack = vec![];
-
-        debug!("process_cycles()");
-
-        for (index, node) in self.nodes.iter().enumerate() {
-            // For some benchmarks this state test is extremely
-            // hot. It's a win to handle the no-op cases immediately to avoid
-            // the cost of the function call.
-            if node.state.get() == NodeState::Success {
-                self.find_cycles_from_node(&mut stack, processor, index);
-            }
-        }
-
-        debug!("process_cycles: complete");
-
-        debug_assert!(stack.is_empty());
-    }
-
-    fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>, processor: &mut P, index: usize)
-        where P: ObligationProcessor<Obligation=O>
-    {
-        let node = &self.nodes[index];
-        if node.state.get() == NodeState::Success {
-            match stack.iter().rposition(|&n| n == index) {
-                None => {
-                    stack.push(index);
-                    for &index in node.dependents.iter() {
-                        self.find_cycles_from_node(stack, processor, index);
-                    }
-                    stack.pop();
-                    node.state.set(NodeState::Done);
-                }
-                Some(rpos) => {
-                    // Cycle detected.
-                    processor.process_backedge(
-                        stack[rpos..].iter().map(GetObligation(&self.nodes)),
-                        PhantomData
-                    );
-                }
-            }
-        }
-    }
-
     /// Returns a vector of obligations for `p` and all of its
     /// ancestors, putting them into the error state in the process.
     fn error_at(&self, mut index: usize) -> Vec<O> {
@@ -560,21 +538,28 @@
         trace
     }
 
+    /// Mark all `Success` nodes that depend on a pending node as still
+    /// waiting. Upon completion, any `Success` nodes that aren't still waiting
+    /// can be removed by `compress`.
+    fn mark_still_waiting_nodes(&self) {
+        for node in &self.nodes {
+            if node.state.get() == NodeState::Pending {
+                // This call site is hot.
+                self.inlined_mark_dependents_as_still_waiting(node);
+            }
+        }
+    }
+
     // This always-inlined function is for the hot call site.
     #[inline(always)]
-    fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
+    fn inlined_mark_dependents_as_still_waiting(&self, node: &Node<O>) {
         for &index in node.dependents.iter() {
             let node = &self.nodes[index];
-            match node.state.get() {
-                NodeState::Waiting | NodeState::Error => {}
-                NodeState::Success => {
-                    node.state.set(NodeState::Waiting);
+            if let NodeState::Success(waiting) = node.state.get() {
+                if !self.is_still_waiting(waiting) {
+                    node.state.set(NodeState::Success(self.still_waiting()));
                     // This call site is cold.
-                    self.uninlined_mark_neighbors_as_waiting_from(node);
-                }
-                NodeState::Pending | NodeState::Done => {
-                    // This call site is cold.
-                    self.uninlined_mark_neighbors_as_waiting_from(node);
+                    self.uninlined_mark_dependents_as_still_waiting(node);
                 }
             }
         }
@@ -582,31 +567,65 @@
 
     // This never-inlined function is for the cold call site.
     #[inline(never)]
-    fn uninlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
-        self.inlined_mark_neighbors_as_waiting_from(node)
+    fn uninlined_mark_dependents_as_still_waiting(&self, node: &Node<O>) {
+        self.inlined_mark_dependents_as_still_waiting(node)
     }
 
-    /// Marks all nodes that depend on a pending node as `NodeState::Waiting`.
-    fn mark_as_waiting(&self) {
-        for node in &self.nodes {
-            if node.state.get() == NodeState::Waiting {
-                node.state.set(NodeState::Success);
+    /// Report cycles between all `Success` nodes that aren't still waiting.
+    /// This must be called after `mark_still_waiting_nodes`.
+    fn process_cycles<P>(&self, processor: &mut P)
+        where P: ObligationProcessor<Obligation=O>
+    {
+        let mut stack = vec![];
+
+        for (index, node) in self.nodes.iter().enumerate() {
+            // For some benchmarks this state test is extremely hot. It's a win
+            // to handle the no-op cases immediately to avoid the cost of the
+            // function call.
+            if let NodeState::Success(waiting) = node.state.get() {
+                if !self.is_still_waiting(waiting) {
+                    self.find_cycles_from_node(&mut stack, processor, index, index);
+                }
             }
         }
 
-        for node in &self.nodes {
-            if node.state.get() == NodeState::Pending {
-                // This call site is hot.
-                self.inlined_mark_neighbors_as_waiting_from(node);
+        debug_assert!(stack.is_empty());
+    }
+
+    fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>, processor: &mut P, min_index: usize,
+                                index: usize)
+        where P: ObligationProcessor<Obligation=O>
+    {
+        let node = &self.nodes[index];
+        if let NodeState::Success(waiting) = node.state.get() {
+            if !self.is_still_waiting(waiting) {
+                match stack.iter().rposition(|&n| n == index) {
+                    None => {
+                        stack.push(index);
+                        for &dep_index in node.dependents.iter() {
+                            // The index check avoids re-considering a node.
+                            if dep_index >= min_index {
+                                self.find_cycles_from_node(stack, processor, min_index, dep_index);
+                            }
+                        }
+                        stack.pop();
+                    }
+                    Some(rpos) => {
+                        // Cycle detected.
+                        processor.process_backedge(
+                            stack[rpos..].iter().map(GetObligation(&self.nodes)),
+                            PhantomData
+                        );
+                    }
+                }
             }
         }
     }
 
     /// Compresses the vector, removing all popped nodes. This adjusts the
-    /// indices and hence invalidates any outstanding indices.
-    ///
-    /// Beforehand, all nodes must be marked as `Done` and no cycles
-    /// on these nodes may be present. This is done by e.g., `process_cycles`.
+    /// indices and hence invalidates any outstanding indices. `process_cycles`
+    /// must be run beforehand to remove any cycles on not-still-waiting
+    /// `Success` nodes.
     #[inline(never)]
     fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
         let orig_nodes_len = self.nodes.len();
@@ -614,10 +633,10 @@
         debug_assert!(node_rewrites.is_empty());
         node_rewrites.extend(0..orig_nodes_len);
         let mut dead_nodes = 0;
-        let mut removed_done_obligations: Vec<O> = vec![];
+        let mut removed_success_obligations: Vec<O> = vec![];
 
-        // Now move all Done/Error nodes to the end, preserving the order of
-        // the Pending/Waiting nodes.
+        // Move removable nodes to the end, preserving the order of the
+        // remaining nodes.
         //
         // LOOP INVARIANT:
         //     self.nodes[0..index - dead_nodes] are the first remaining nodes
@@ -626,13 +645,19 @@
         for index in 0..orig_nodes_len {
             let node = &self.nodes[index];
             match node.state.get() {
-                NodeState::Pending | NodeState::Waiting => {
+                NodeState::Pending => {
                     if dead_nodes > 0 {
                         self.nodes.swap(index, index - dead_nodes);
                         node_rewrites[index] -= dead_nodes;
                     }
                 }
-                NodeState::Done => {
+                NodeState::Success(waiting) if self.is_still_waiting(waiting) => {
+                    if dead_nodes > 0 {
+                        self.nodes.swap(index, index - dead_nodes);
+                        node_rewrites[index] -= dead_nodes;
+                    }
+                }
+                NodeState::Success(_) => {
                     // This lookup can fail because the contents of
                     // `self.active_cache` are not guaranteed to match those of
                     // `self.nodes`. See the comment in `process_obligation`
@@ -646,7 +671,7 @@
                     }
                     if do_completed == DoCompleted::Yes {
                         // Extract the success stories.
-                        removed_done_obligations.push(node.obligation.clone());
+                        removed_success_obligations.push(node.obligation.clone());
                     }
                     node_rewrites[index] = orig_nodes_len;
                     dead_nodes += 1;
@@ -660,7 +685,6 @@
                     node_rewrites[index] = orig_nodes_len;
                     dead_nodes += 1;
                 }
-                NodeState::Success => unreachable!()
             }
         }
 
@@ -674,7 +698,7 @@
         self.node_rewrites.replace(node_rewrites);
 
         if do_completed == DoCompleted::Yes {
-            Some(removed_done_obligations)
+            Some(removed_success_obligations)
         } else {
             None
         }
diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs
index 86f59bf..f9bfe5a 100644
--- a/src/librustc_data_structures/profiling.rs
+++ b/src/librustc_data_structures/profiling.rs
@@ -7,7 +7,7 @@
 use std::thread::ThreadId;
 use std::u32;
 
-use measureme::{StringId, TimestampKind};
+use measureme::{StringId};
 
 /// MmapSerializatioSink is faster on macOS and Linux
 /// but FileSerializationSink is faster on Windows
@@ -63,8 +63,8 @@
     ("incr-cache-load", EventFilter::INCR_CACHE_LOADS),
 ];
 
-fn thread_id_to_u64(tid: ThreadId) -> u64 {
-    unsafe { mem::transmute::<ThreadId, u64>(tid) }
+fn thread_id_to_u32(tid: ThreadId) -> u32 {
+    unsafe { mem::transmute::<ThreadId, u64>(tid) as u32 }
 }
 
 
@@ -149,11 +149,10 @@
     /// Record a query in-memory cache hit.
     #[inline(always)]
     pub fn query_cache_hit(&self, query_name: impl QueryName) {
-        self.non_guard_query_event(
+        self.instant_query_event(
             |profiler| profiler.query_cache_hit_event_kind,
             query_name,
             EventFilter::QUERY_CACHE_HITS,
-            TimestampKind::Instant,
         );
     }
 
@@ -184,22 +183,20 @@
     }
 
     #[inline(always)]
-    fn non_guard_query_event(
+    fn instant_query_event(
         &self,
         event_kind: fn(&SelfProfiler) -> StringId,
         query_name: impl QueryName,
         event_filter: EventFilter,
-        timestamp_kind: TimestampKind
     ) {
         drop(self.exec(event_filter, |profiler| {
             let event_id = SelfProfiler::get_query_name_string_id(query_name);
-            let thread_id = thread_id_to_u64(std::thread::current().id());
+            let thread_id = thread_id_to_u32(std::thread::current().id());
 
-            profiler.profiler.record_event(
+            profiler.profiler.record_instant_event(
                 event_kind(profiler),
                 event_id,
                 thread_id,
-                timestamp_kind,
             );
 
             TimingGuard::none()
@@ -306,7 +303,7 @@
         event_kind: StringId,
         event_id: StringId,
     ) -> TimingGuard<'a> {
-        let thread_id = thread_id_to_u64(std::thread::current().id());
+        let thread_id = thread_id_to_u32(std::thread::current().id());
         let raw_profiler = &profiler.profiler;
         let timing_guard = raw_profiler.start_recording_interval_event(event_kind,
                                                                        event_id,
diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs
index 371f0f6..78cbc12 100644
--- a/src/librustc_data_structures/tiny_list.rs
+++ b/src/librustc_data_structures/tiny_list.rs
@@ -16,41 +16,29 @@
 
 #[derive(Clone)]
 pub struct TinyList<T: PartialEq> {
-    head: Option<Element<T>>
+    head: Option<Element<T>>,
 }
 
 impl<T: PartialEq> TinyList<T> {
     #[inline]
     pub fn new() -> TinyList<T> {
-        TinyList {
-            head: None
-        }
+        TinyList { head: None }
     }
 
     #[inline]
     pub fn new_single(data: T) -> TinyList<T> {
-        TinyList {
-            head: Some(Element {
-                data,
-                next: None,
-            })
-        }
+        TinyList { head: Some(Element { data, next: None }) }
     }
 
     #[inline]
     pub fn insert(&mut self, data: T) {
-        self.head = Some(Element {
-            data,
-            next: self.head.take().map(Box::new)
-        });
+        self.head = Some(Element { data, next: self.head.take().map(Box::new) });
     }
 
     #[inline]
     pub fn remove(&mut self, data: &T) -> bool {
         self.head = match self.head {
-            Some(ref mut head) if head.data == *data => {
-                head.next.take().map(|x| *x)
-            }
+            Some(ref mut head) if head.data == *data => head.next.take().map(|x| *x),
             Some(ref mut head) => return head.remove_next(data),
             None => return false,
         };
@@ -88,12 +76,16 @@
 
 impl<T: PartialEq> Element<T> {
     fn remove_next(&mut self, data: &T) -> bool {
-        let new_next = match self.next {
-            Some(ref mut next) if next.data == *data => next.next.take(),
-            Some(ref mut next) => return next.remove_next(data),
-            None => return false,
-        };
-        self.next = new_next;
-        true
+        let mut n = self;
+        loop {
+            match n.next {
+                Some(ref mut next) if next.data == *data => {
+                    n.next = next.next.take();
+                    return true;
+                }
+                Some(ref mut next) => n = next,
+                None => return false,
+            }
+        }
     }
 }
diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs
index a3926c1..bbf6999 100644
--- a/src/librustc_data_structures/transitive_relation.rs
+++ b/src/librustc_data_structures/transitive_relation.rs
@@ -373,6 +373,14 @@
         }
         matrix
     }
+
+    /// Lists all the base edges in the graph: the initial _non-transitive_ set of element
+    /// relations, which will be later used as the basis for the transitive closure computation.
+    pub fn base_edges(&self) -> impl Iterator<Item=(&T, &T)> {
+        self.edges
+            .iter()
+            .map(move |edge| (&self.elements[edge.source.0], &self.elements[edge.target.0]))
+    }
 }
 
 /// Pare down is used as a step in the LUB computation. It edits the
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index d1cb4cb..043cfc5 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -32,3 +32,6 @@
 rustc_resolve = { path = "../librustc_resolve" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
+
+[features]
+llvm = ['rustc_interface/llvm']
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 0594550..3230e04 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -42,7 +42,7 @@
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use errors::{PResult, registry::Registry};
 use rustc_interface::{interface, Queries};
-use rustc_interface::util::get_codegen_sysroot;
+use rustc_interface::util::get_builtin_codegen_backend;
 use rustc_data_structures::sync::SeqCst;
 use rustc_feature::{find_gated_cfg, UnstableFeatures};
 use rustc_serialize::json::ToJson;
@@ -765,7 +765,7 @@
         println!("commit-date: {}", unw(commit_date_str()));
         println!("host: {}", config::host_triple());
         println!("release: {}", unw(release_str()));
-        get_codegen_sysroot("llvm")().print_version();
+        get_builtin_codegen_backend("llvm")().print_version();
     }
 }
 
@@ -1059,7 +1059,7 @@
     }
 
     if cg_flags.iter().any(|x| *x == "passes=list") {
-        get_codegen_sysroot("llvm")().print_passes();
+        get_builtin_codegen_backend("llvm")().print_passes();
         return None;
     }
 
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 7f111b4..9c1bec3 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -18,7 +18,6 @@
 E0013: include_str!("./error_codes/E0013.md"),
 E0014: include_str!("./error_codes/E0014.md"),
 E0015: include_str!("./error_codes/E0015.md"),
-E0017: include_str!("./error_codes/E0017.md"),
 E0019: include_str!("./error_codes/E0019.md"),
 E0023: include_str!("./error_codes/E0023.md"),
 E0025: include_str!("./error_codes/E0025.md"),
@@ -347,6 +346,7 @@
 E0623: include_str!("./error_codes/E0623.md"),
 E0624: include_str!("./error_codes/E0624.md"),
 E0626: include_str!("./error_codes/E0626.md"),
+E0631: include_str!("./error_codes/E0631.md"),
 E0633: include_str!("./error_codes/E0633.md"),
 E0635: include_str!("./error_codes/E0635.md"),
 E0636: include_str!("./error_codes/E0636.md"),
@@ -580,7 +580,6 @@
     // rustc_const_unstable attribute must be paired with stable/unstable
     // attribute
     E0630,
-    E0631, // type mismatch in closure arguments
     E0632, // cannot provide explicit generic arguments when `impl Trait` is
            // used in argument position
     E0634, // type has conflicting packed representaton hints
diff --git a/src/librustc_error_codes/error_codes/E0017.md b/src/librustc_error_codes/error_codes/E0017.md
deleted file mode 100644
index d5e6857..0000000
--- a/src/librustc_error_codes/error_codes/E0017.md
+++ /dev/null
@@ -1,20 +0,0 @@
-References in statics and constants may only refer to immutable values.
-
-Erroneous code example:
-
-```compile_fail,E0017
-static X: i32 = 1;
-const C: i32 = 2;
-
-// these three are not allowed:
-const CR: &mut i32 = &mut C;
-static STATIC_REF: &'static mut i32 = &mut X;
-static CONST_REF: &'static mut i32 = &mut C;
-```
-
-Statics are shared everywhere, and if they refer to mutable data one might
-violate memory safety since holding multiple mutable references to shared data
-is not allowed.
-
-If you really want global mutable state, try using `static mut` or a global
-`UnsafeCell`.
diff --git a/src/librustc_error_codes/error_codes/E0092.md b/src/librustc_error_codes/error_codes/E0092.md
index 2750a7d..e289534 100644
--- a/src/librustc_error_codes/error_codes/E0092.md
+++ b/src/librustc_error_codes/error_codes/E0092.md
@@ -1,4 +1,5 @@
-You tried to declare an undefined atomic operation function.
+An undefined atomic operation function was declared.
+
 Erroneous code example:
 
 ```compile_fail,E0092
@@ -11,8 +12,8 @@
 ```
 
 Please check you didn't make a mistake in the function's name. All intrinsic
-functions are defined in librustc_codegen_llvm/intrinsic.rs and in
-libcore/intrinsics.rs in the Rust source code. Example:
+functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in
+`libcore/intrinsics.rs` in the Rust source code. Example:
 
 ```
 #![feature(intrinsics)]
diff --git a/src/librustc_error_codes/error_codes/E0093.md b/src/librustc_error_codes/error_codes/E0093.md
index 9633f79..8e7de1a 100644
--- a/src/librustc_error_codes/error_codes/E0093.md
+++ b/src/librustc_error_codes/error_codes/E0093.md
@@ -1,4 +1,6 @@
-You declared an unknown intrinsic function. Erroneous code example:
+An unknown intrinsic function was declared.
+
+Erroneous code example:
 
 ```compile_fail,E0093
 #![feature(intrinsics)]
@@ -15,8 +17,8 @@
 ```
 
 Please check you didn't make a mistake in the function's name. All intrinsic
-functions are defined in librustc_codegen_llvm/intrinsic.rs and in
-libcore/intrinsics.rs in the Rust source code. Example:
+functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in
+`libcore/intrinsics.rs` in the Rust source code. Example:
 
 ```
 #![feature(intrinsics)]
diff --git a/src/librustc_error_codes/error_codes/E0094.md b/src/librustc_error_codes/error_codes/E0094.md
index 4d27f61..42baa65 100644
--- a/src/librustc_error_codes/error_codes/E0094.md
+++ b/src/librustc_error_codes/error_codes/E0094.md
@@ -1,4 +1,5 @@
-You gave an invalid number of type parameters to an intrinsic function.
+An invalid number of type parameters was given to an intrinsic function.
+
 Erroneous code example:
 
 ```compile_fail,E0094
diff --git a/src/librustc_error_codes/error_codes/E0106.md b/src/librustc_error_codes/error_codes/E0106.md
index 8a49c1f..60ca1dd 100644
--- a/src/librustc_error_codes/error_codes/E0106.md
+++ b/src/librustc_error_codes/error_codes/E0106.md
@@ -2,7 +2,7 @@
 inside a function signature, the problem may be with failing to adhere to the
 lifetime elision rules (see below).
 
-Here are some simple examples of where you'll run into this error:
+Erroneous code examples:
 
 ```compile_fail,E0106
 struct Foo1 { x: &bool }
@@ -27,7 +27,7 @@
 For more background on lifetime elision see [the book][book-le].
 
 The lifetime elision rules require that any function signature with an elided
-output lifetime must either have
+output lifetime must either have:
 
  - exactly one input lifetime
  - or, multiple input lifetimes, but the function must also be a method with a
diff --git a/src/librustc_error_codes/error_codes/E0107.md b/src/librustc_error_codes/error_codes/E0107.md
index bfe0d21..4d22b17 100644
--- a/src/librustc_error_codes/error_codes/E0107.md
+++ b/src/librustc_error_codes/error_codes/E0107.md
@@ -1,4 +1,6 @@
-This error means that an incorrect number of generic arguments were provided:
+An incorrect number of generic arguments were provided.
+
+Erroneous code example:
 
 ```compile_fail,E0107
 struct Foo<T> { x: T }
@@ -9,6 +11,7 @@
                                   //        expected 1, found 2
 
 fn foo<T, U>(x: T, y: U) {}
+fn f() {}
 
 fn main() {
     let x: bool = true;
@@ -16,12 +19,26 @@
                                     //        expected 2, found 1
     foo::<bool, i32, i32>(x, 2, 4); // error: wrong number of type arguments:
                                     //        expected 2, found 3
+    f::<'static>();                 // error: wrong number of lifetime arguments
+                                    //        expected 0, found 1
 }
+```
 
+When using/declaring an item with generic arguments, you must provide the exact
+same number:
+
+```
+struct Foo<T> { x: T }
+
+struct Bar<T> { x: Foo<T> }               // ok!
+struct Baz<S, T> { x: Foo<S>, y: Foo<T> } // ok!
+
+fn foo<T, U>(x: T, y: U) {}
 fn f() {}
 
 fn main() {
-    f::<'static>(); // error: wrong number of lifetime arguments:
-                    //        expected 0, found 1
+    let x: bool = true;
+    foo::<bool, u32>(x, 12);              // ok!
+    f();                                  // ok!
 }
 ```
diff --git a/src/librustc_error_codes/error_codes/E0109.md b/src/librustc_error_codes/error_codes/E0109.md
index 5bc229a..2eab972 100644
--- a/src/librustc_error_codes/error_codes/E0109.md
+++ b/src/librustc_error_codes/error_codes/E0109.md
@@ -1,4 +1,5 @@
 You tried to provide a generic argument to a type which doesn't need it.
+
 Erroneous code example:
 
 ```compile_fail,E0109
diff --git a/src/librustc_error_codes/error_codes/E0116.md b/src/librustc_error_codes/error_codes/E0116.md
index 27759a4..ca849c2 100644
--- a/src/librustc_error_codes/error_codes/E0116.md
+++ b/src/librustc_error_codes/error_codes/E0116.md
@@ -1,11 +1,15 @@
-You can only define an inherent implementation for a type in the same crate
-where the type was defined. For example, an `impl` block as below is not allowed
-since `Vec` is defined in the standard library:
+An inherent implementation was defined for a type outside the current crate.
+
+Erroneous code example:
 
 ```compile_fail,E0116
 impl Vec<u8> { } // error
 ```
 
+You can only define an inherent implementation for a type in the same crate
+where the type was defined. For example, an `impl` block as above is not allowed
+since `Vec` is defined in the standard library.
+
 To fix this problem, you can do either of these things:
 
  - define a trait that has the desired associated functions/types/constants and
diff --git a/src/librustc_error_codes/error_codes/E0117.md b/src/librustc_error_codes/error_codes/E0117.md
index bd36230..7fa211d 100644
--- a/src/librustc_error_codes/error_codes/E0117.md
+++ b/src/librustc_error_codes/error_codes/E0117.md
@@ -1,3 +1,11 @@
+The `Drop` trait was implemented on a non-struct type.
+
+Erroneous code example:
+
+```compile_fail,E0117
+impl Drop for u32 {}
+```
+
 This error indicates a violation of one of Rust's orphan rules for trait
 implementations. The rule prohibits any implementation of a foreign trait (a
 trait defined in another crate) where
@@ -6,12 +14,6 @@
  - all of the parameters being passed to the trait (if there are any) are also
    foreign.
 
-Here's one example of this error:
-
-```compile_fail,E0117
-impl Drop for u32 {}
-```
-
 To avoid this kind of error, ensure that at least one local type is referenced
 by the `impl`:
 
diff --git a/src/librustc_error_codes/error_codes/E0118.md b/src/librustc_error_codes/error_codes/E0118.md
index baf35ff..5cb5f50 100644
--- a/src/librustc_error_codes/error_codes/E0118.md
+++ b/src/librustc_error_codes/error_codes/E0118.md
@@ -1,5 +1,7 @@
-You're trying to write an inherent implementation for something which isn't a
-struct nor an enum. Erroneous code example:
+An inherent implementation was defined for something which isn't a struct nor
+an enum.
+
+Erroneous code example:
 
 ```compile_fail,E0118
 impl (u8, u8) { // error: no base type found for inherent implementation
diff --git a/src/librustc_error_codes/error_codes/E0119.md b/src/librustc_error_codes/error_codes/E0119.md
index 0af3bd4..e596349 100644
--- a/src/librustc_error_codes/error_codes/E0119.md
+++ b/src/librustc_error_codes/error_codes/E0119.md
@@ -1,5 +1,6 @@
 There are conflicting trait implementations for the same type.
-Example of erroneous code:
+
+Erroneous code example:
 
 ```compile_fail,E0119
 trait MyTrait {
diff --git a/src/librustc_error_codes/error_codes/E0478.md b/src/librustc_error_codes/error_codes/E0478.md
index 6634d9b..4bc5fde 100644
--- a/src/librustc_error_codes/error_codes/E0478.md
+++ b/src/librustc_error_codes/error_codes/E0478.md
@@ -21,8 +21,8 @@
 ```
 trait Wedding<'t>: 't { }
 
-struct Prince<'kiss, 'SnowWhite: 'kiss> { // You say here that 'kiss must live
-                                          // longer than 'SnowWhite.
+struct Prince<'kiss, 'SnowWhite: 'kiss> { // You say here that 'SnowWhite
+                                          // must live longer than 'kiss.
     child: Box<Wedding<'kiss> + 'SnowWhite>, // And now it's all good!
 }
 ```
diff --git a/src/librustc_error_codes/error_codes/E0631.md b/src/librustc_error_codes/error_codes/E0631.md
new file mode 100644
index 0000000..6188d5f
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0631.md
@@ -0,0 +1,27 @@
+This error indicates a type mismatch in closure arguments.
+
+Erroneous code example:
+
+```compile_fail,E0631
+fn foo<F: Fn(i32)>(f: F) {
+}
+
+fn main() {
+    foo(|x: &str| {});
+}
+```
+
+The error occurs because `foo` accepts a closure that takes an `i32` argument,
+but in `main`, it is passed a closure with a `&str` argument.
+
+This can be resolved by changing the type annotation or removing it entirely
+if it can be inferred.
+
+```
+fn foo<F: Fn(i32)>(f: F) {
+}
+
+fn main() {
+    foo(|x: i32| {});
+}
+```
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index abec979..744f4a4 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -498,10 +498,20 @@
         self
     }
 
+    pub fn clear_code(&mut self) -> &mut Self {
+        self.code = None;
+        self
+    }
+
     pub fn get_code(&self) -> Option<DiagnosticId> {
         self.code.clone()
     }
 
+    pub fn set_primary_message<M: Into<String>>(&mut self, msg: M) -> &mut Self {
+        self.message[0] = (msg.into(), Style::NoStyle);
+        self
+    }
+
     pub fn message(&self) -> String {
         self.message.iter().map(|i| i.0.as_str()).collect::<String>()
     }
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index fc880b9..363621b 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -523,6 +523,9 @@
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
 
+    /// Allows using `&mut` in constant functions.
+    (active, const_mut_refs, "1.41.0", Some(57349), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -538,5 +541,4 @@
     sym::or_patterns,
     sym::let_chains,
     sym::raw_dylib,
-    sym::track_caller,
 ];
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index 7ab5ec2..58fd928 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -25,6 +25,7 @@
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }
 rustc_codegen_utils = { path = "../librustc_codegen_utils" }
+rustc_codegen_llvm = { path = "../librustc_codegen_llvm", optional = true }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
 rustc_passes = { path = "../librustc_passes" }
@@ -39,3 +40,6 @@
 
 [dev-dependencies]
 rustc_target = { path = "../librustc_target" }
+
+[features]
+llvm = ['rustc_codegen_llvm']
diff --git a/src/librustc_interface/lib.rs b/src/librustc_interface/lib.rs
index 76af434..9bb1878 100644
--- a/src/librustc_interface/lib.rs
+++ b/src/librustc_interface/lib.rs
@@ -1,3 +1,4 @@
+#![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(set_stdio)]
 #![feature(nll)]
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 2351843..2a4bc41 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -547,13 +547,7 @@
 }
 
 fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> {
-    let check = |output_path: &PathBuf| {
-        if output_path.is_dir() {
-            Some(output_path.clone())
-        } else {
-            None
-        }
-    };
+    let check = |output_path: &PathBuf| output_path.is_dir().then(|| output_path.clone());
     check_output(output_paths, check)
 }
 
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index 6103d42..e429b4d 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -22,7 +22,7 @@
 use syntax::{self, ast};
 
 /// Represent the result of a query.
-/// This result can be stolen with the `take` method and returned with the `give` method.
+/// This result can be stolen with the `take` method and generated with the `compute` method.
 pub struct Query<T> {
     result: RefCell<Option<Result<T>>>,
 }
@@ -37,7 +37,7 @@
     }
 
     /// Takes ownership of the query result. Further attempts to take or peek the query
-    /// result will panic unless it is returned by calling the `give` method.
+    /// result will panic unless it is generated by calling the `compute` method.
     pub fn take(&self) -> T {
         self.result
             .borrow_mut()
@@ -117,11 +117,9 @@
 
     pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
         self.dep_graph_future.compute(|| {
-            Ok(if self.session().opts.build_dep_graph() {
-                Some(rustc_incremental::load_dep_graph(self.session()))
-            } else {
-                None
-            })
+            Ok(self.session().opts.build_dep_graph().then(|| {
+                rustc_incremental::load_dep_graph(self.session())
+            }))
         })
     }
 
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index 4c630b5..d4b5e83 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -7,7 +7,7 @@
 use rustc::session::config::{build_configuration, build_session_options, to_crate_config};
 use rustc::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry};
 use rustc::session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion};
-use rustc::session::config::{rustc_optgroups, Options, ErrorOutputType, Passes};
+use rustc::session::config::{rustc_optgroups, Options, ErrorOutputType, Passes, ExternLocation};
 use rustc::session::{build_session, Session};
 use rustc::session::search_paths::SearchPath;
 use std::collections::{BTreeMap, BTreeSet};
@@ -38,14 +38,15 @@
 fn new_public_extern_entry<S, I>(locations: I) -> ExternEntry
 where
     S: Into<String>,
-    I: IntoIterator<Item = Option<S>>,
+    I: IntoIterator<Item = S>,
 {
-    let locations: BTreeSet<_> = locations.into_iter().map(|o| o.map(|s| s.into()))
+    let locations: BTreeSet<_> = locations.into_iter().map(|s| s.into())
         .collect();
 
     ExternEntry {
-        locations,
-        is_private_dep: false
+        location: ExternLocation::ExactPaths(locations),
+        is_private_dep: false,
+        add_prelude: true,
     }
 }
 
@@ -160,33 +161,33 @@
     v1.externs = Externs::new(mk_map(vec![
         (
             String::from("a"),
-            new_public_extern_entry(vec![Some("b"), Some("c")])
+            new_public_extern_entry(vec!["b", "c"])
         ),
         (
             String::from("d"),
-            new_public_extern_entry(vec![Some("e"), Some("f")])
+            new_public_extern_entry(vec!["e", "f"])
         ),
     ]));
 
     v2.externs = Externs::new(mk_map(vec![
         (
             String::from("d"),
-            new_public_extern_entry(vec![Some("e"), Some("f")])
+            new_public_extern_entry(vec!["e", "f"])
         ),
         (
             String::from("a"),
-            new_public_extern_entry(vec![Some("b"), Some("c")])
+            new_public_extern_entry(vec!["b", "c"])
         ),
     ]));
 
     v3.externs = Externs::new(mk_map(vec![
         (
             String::from("a"),
-            new_public_extern_entry(vec![Some("b"), Some("c")])
+            new_public_extern_entry(vec!["b", "c"])
         ),
         (
             String::from("d"),
-            new_public_extern_entry(vec![Some("f"), Some("e")])
+            new_public_extern_entry(vec!["f", "e"])
         ),
     ]));
 
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index d8e20e1..c78b3ee 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -16,11 +16,9 @@
 use rustc_metadata::dynamic_lib::DynamicLibrary;
 use rustc_resolve::{self, Resolver};
 use std::env;
-use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::io::{self, Write};
 use std::mem;
 use std::path::{Path, PathBuf};
-use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::{Arc, Mutex, Once};
 use std::ops::DerefMut;
 use smallvec::SmallVec;
@@ -107,11 +105,7 @@
 fn get_stack_size() -> Option<usize> {
     // FIXME: Hacks on hacks. If the env is trying to override the stack size
     // then *don't* set it explicitly.
-    if env::var_os("RUST_MIN_STACK").is_none() {
-        Some(STACK_SIZE)
-    } else {
-        None
-    }
+    env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE)
 }
 
 struct Sink(Arc<Mutex<Vec<u8>>>);
@@ -253,7 +247,7 @@
             filename if filename.contains(".") => {
                 load_backend_from_dylib(filename.as_ref())
             }
-            codegen_name => get_codegen_sysroot(codegen_name),
+            codegen_name => get_builtin_codegen_backend(codegen_name),
         };
 
         unsafe {
@@ -285,11 +279,7 @@
             } else {
                 "rustc"
             });
-            if candidate.exists() {
-                Some(candidate)
-            } else {
-                None
-            }
+            candidate.exists().then_some(candidate)
         })
         .next()
 }
@@ -392,83 +382,16 @@
     }
 }
 
-pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
-    // For now we only allow this function to be called once as it'll dlopen a
-    // few things, which seems to work best if we only do that once. In
-    // general this assertion never trips due to the once guard in `get_codegen_backend`,
-    // but there's a few manual calls to this function in this file we protect
-    // against.
-    static LOADED: AtomicBool = AtomicBool::new(false);
-    assert!(!LOADED.fetch_or(true, Ordering::SeqCst),
-            "cannot load the default codegen backend twice");
-
-    let target = session::config::host_triple();
-    let sysroot_candidates = sysroot_candidates();
-
-    let sysroot = sysroot_candidates.iter()
-        .map(|sysroot| {
-            let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
-            sysroot.join(libdir).with_file_name(
-                option_env!("CFG_CODEGEN_BACKENDS_DIR").unwrap_or("codegen-backends"))
-        })
-        .filter(|f| {
-            info!("codegen backend candidate: {}", f.display());
-            f.exists()
-        })
-        .next();
-    let sysroot = sysroot.unwrap_or_else(|| {
-        let candidates = sysroot_candidates.iter()
-            .map(|p| p.display().to_string())
-            .collect::<Vec<_>>()
-            .join("\n* ");
-        let err = format!("failed to find a `codegen-backends` folder \
-                           in the sysroot candidates:\n* {}", candidates);
-        early_error(ErrorOutputType::default(), &err);
-    });
-    info!("probing {} for a codegen backend", sysroot.display());
-
-    let d = sysroot.read_dir().unwrap_or_else(|e| {
-        let err = format!("failed to load default codegen backend, couldn't \
-                           read `{}`: {}", sysroot.display(), e);
-        early_error(ErrorOutputType::default(), &err);
-    });
-
-    let mut file: Option<PathBuf> = None;
-
-    let expected_name = format!("rustc_codegen_llvm-{}", backend_name);
-    for entry in d.filter_map(|e| e.ok()) {
-        let path = entry.path();
-        let filename = match path.file_name().and_then(|s| s.to_str()) {
-            Some(s) => s,
-            None => continue,
-        };
-        if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) {
-            continue
-        }
-        let name = &filename[DLL_PREFIX.len() .. filename.len() - DLL_SUFFIX.len()];
-        if name != expected_name {
-            continue
-        }
-        if let Some(ref prev) = file {
-            let err = format!("duplicate codegen backends found\n\
-                               first:  {}\n\
-                               second: {}\n\
-            ", prev.display(), path.display());
-            early_error(ErrorOutputType::default(), &err);
-        }
-        file = Some(path.clone());
-    }
-
-    match file {
-        Some(ref s) => return load_backend_from_dylib(s),
-        None => {
-            let err = format!("failed to load default codegen backend for `{}`, \
-                               no appropriate codegen dylib found in `{}`",
-                              backend_name, sysroot.display());
-            early_error(ErrorOutputType::default(), &err);
+pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
+    #[cfg(feature = "llvm")]
+    {
+        if backend_name == "llvm" {
+            return rustc_codegen_llvm::LlvmCodegenBackend::new;
         }
     }
 
+    let err = format!("unsupported builtin codegen backend `{}`", backend_name);
+    early_error(ErrorOutputType::default(), &err);
 }
 
 pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 0fd7145f..10b00d3 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1491,11 +1491,7 @@
             match pred {
                 ty::Predicate::TypeOutlives(outlives) => {
                     let outlives = outlives.skip_binder();
-                    if outlives.0.is_param(index) {
-                        Some(outlives.1)
-                    } else {
-                        None
-                    }
+                    outlives.0.is_param(index).then_some(outlives.1)
                 }
                 _ => None
             }
@@ -1554,11 +1550,7 @@
                             }),
                         _ => false,
                     };
-                    if is_inferred {
-                        Some((i, bound.span()))
-                    } else {
-                        None
-                    }
+                    is_inferred.then_some((i, bound.span()))
                 } else {
                     None
                 }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index e60c025..b77f2cb 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -12,6 +12,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![cfg_attr(test, feature(test))]
+#![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(nll)]
@@ -340,7 +341,7 @@
         "converted into hard error, see https://github.com/rust-lang/rust/issues/46205");
     store.register_removed("legacy_constructor_visibility",
         "converted into hard error, see https://github.com/rust-lang/rust/issues/39207");
-    store.register_removed("legacy_disrectory_ownership",
+    store.register_removed("legacy_directory_ownership",
         "converted into hard error, see https://github.com/rust-lang/rust/issues/37872");
     store.register_removed("safe_extern_statics",
         "converted into hard error, see https://github.com/rust-lang/rust/issues/36247");
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index f7de7ec..e6f39cc 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -355,7 +355,9 @@
         match value.kind {
             ast::ExprKind::Paren(ref inner) => {
                 if !Self::is_expr_parens_necessary(inner, followed_by_block) &&
-                    value.attrs.is_empty() {
+                    value.attrs.is_empty() &&
+                    !value.span.from_expansion()
+                {
                     let expr_text = if let Ok(snippet) = cx.sess().source_map()
                         .span_to_snippet(value.span) {
                             snippet
diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml
index 0fe327d..4fc02e3 100644
--- a/src/librustc_llvm/Cargo.toml
+++ b/src/librustc_llvm/Cargo.toml
@@ -13,6 +13,9 @@
 static-libstdcpp = []
 emscripten = []
 
+[dependencies]
+libc = "0.2"
+
 [build-dependencies]
 build_helper = { path = "../build_helper" }
 cc = "1.0.1"
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 647d473..9c8943a 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -5,6 +5,26 @@
 
 // NOTE: This crate only exists to allow linking on mingw targets.
 
+use std::cell::RefCell;
+use std::slice;
+use libc::{c_char, size_t};
+
+
+#[repr(C)]
+pub struct RustString {
+    pub bytes: RefCell<Vec<u8>>,
+}
+
+/// Appending to a Rust string -- used by RawRustStringOstream.
+#[no_mangle]
+pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString,
+                                                 ptr: *const c_char,
+                                                 size: size_t) {
+    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
+
+    sr.bytes.borrow_mut().extend_from_slice(slice);
+}
+
 /// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`.
 /// N.B., this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s.
 pub fn initialize_available_targets() {
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index b70cc52..88d1c50 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -12,7 +12,7 @@
 [dependencies]
 flate2 = "1.0"
 log = "0.4"
-memmap = "0.6"
+memmap = "0.7"
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index dbf2dcf..0a0f256 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -218,13 +218,14 @@
             let source = self.cstore.get_crate_data(cnum).source();
             if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) {
                 // Only use `--extern crate_name=path` here, not `--extern crate_name`.
-                let found = entry.locations.iter().filter_map(|l| l.as_ref()).any(|l| {
-                    let l = fs::canonicalize(l).ok();
-                    source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
-                    source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
-                });
-                if found {
-                    ret = Some(cnum);
+                if let Some(mut files) = entry.files() {
+                    if files.any(|l| {
+                        let l = fs::canonicalize(l).ok();
+                        source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
+                        source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
+                    }) {
+                        ret = Some(cnum);
+                    }
                 }
                 return
             }
@@ -802,11 +803,8 @@
         // First up we check for global allocators. Look at the crate graph here
         // and see what's a global allocator, including if we ourselves are a
         // global allocator.
-        let mut global_allocator = if self.cstore.has_global_allocator {
-            Some(Symbol::intern("this crate"))
-        } else {
-            None
-        };
+        let mut global_allocator = self.cstore.has_global_allocator
+            .then(|| Symbol::intern("this crate"));
         self.cstore.iter_crate_data(|_, data| {
             if !data.has_global_allocator() {
                 return
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 8c0b734..aaaff7e 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -1,5 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(core_intrinsics)]
 #![feature(crate_visibility_modifier)]
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index c6fb80e..8a1eeea 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -328,8 +328,9 @@
             crate_name,
             exact_paths: if hash.is_none() {
                 sess.opts.externs.get(&crate_name.as_str()).into_iter()
-                    .flat_map(|entry| entry.locations.iter())
-                    .filter_map(|location| location.clone().map(PathBuf::from)).collect()
+                    .filter_map(|entry| entry.files())
+                    .flatten()
+                    .map(|location| PathBuf::from(location)).collect()
             } else {
                 // SVH being specified means this is a transitive dependency,
                 // so `--extern` options do not apply.
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 6edd17f..0107a22 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -18,7 +18,7 @@
 use rustc_data_structures::svh::Svh;
 use rustc::dep_graph::{self, DepNodeIndex};
 use rustc::middle::lang_items;
-use rustc::mir::{self, BodyCache, interpret, Promoted};
+use rustc::mir::{self, BodyAndCache, interpret, Promoted};
 use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -1079,7 +1079,7 @@
             self.root.per_def.mir.get(self, id).is_some()
     }
 
-    fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> BodyCache<'tcx> {
+    fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> BodyAndCache<'tcx> {
         let mut cache = self.root.per_def.mir.get(self, id)
             .filter(|_| !self.is_proc_macro(id))
             .unwrap_or_else(|| {
@@ -1094,7 +1094,7 @@
         &self,
         tcx: TyCtxt<'tcx>,
         id: DefIndex,
-    ) -> IndexVec<Promoted, BodyCache<'tcx>> {
+    ) -> IndexVec<Promoted, BodyAndCache<'tcx>> {
         let mut cache = self.root.per_def.promoted_mir.get(self, id)
             .filter(|_| !self.is_proc_macro(id))
             .unwrap_or_else(|| {
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index fdf43f0..5abae42 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -276,8 +276,8 @@
     // Also, as an optimization, a missing entry indicates an empty `&[]`.
     inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
     super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
-    mir: Table<DefIndex, Lazy!(mir::BodyCache<'tcx>)>,
-    promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::BodyCache<'tcx>>)>,
+    mir: Table<DefIndex, Lazy!(mir::BodyAndCache<'tcx>)>,
+    promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::BodyAndCache<'tcx>>)>,
 }
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 4afbb4d..7e3bd98 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -16,7 +16,7 @@
 itertools = "0.8"
 log = "0.4"
 log_settings = "0.1.1"
-polonius-engine  = "0.10.0"
+polonius-engine = "0.11.0"
 rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index 802464c..2980483 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -5,7 +5,7 @@
 use crate::dataflow::move_paths::MoveData;
 use rustc::mir::traversal;
 use rustc::mir::visit::{PlaceContext, Visitor, NonUseContext, MutatingUseContext};
-use rustc::mir::{self, Location, Body, Local, ReadOnlyBodyCache};
+use rustc::mir::{self, Location, Body, Local, ReadOnlyBodyAndCache};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_index::vec::IndexVec;
@@ -90,7 +90,7 @@
 impl LocalsStateAtExit {
     fn build(
         locals_are_invalidated_at_exit: bool,
-        body: ReadOnlyBodyCache<'_, 'tcx>,
+        body: ReadOnlyBodyAndCache<'_, 'tcx>,
         move_data: &MoveData<'tcx>
     ) -> Self {
         struct HasStorageDead(BitSet<Local>);
@@ -124,7 +124,7 @@
 impl<'tcx> BorrowSet<'tcx> {
     pub fn build(
         tcx: TyCtxt<'tcx>,
-        body: ReadOnlyBodyCache<'_, 'tcx>,
+        body: ReadOnlyBodyAndCache<'_, 'tcx>,
         locals_are_invalidated_at_exit: bool,
         move_data: &MoveData<'tcx>,
     ) -> Self {
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/constraint_generation.rs
similarity index 95%
rename from src/librustc_mir/borrow_check/nll/constraint_generation.rs
rename to src/librustc_mir/borrow_check/constraint_generation.rs
index cae3030..28a631a 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/constraint_generation.rs
@@ -1,9 +1,3 @@
-use crate::borrow_check::borrow_set::BorrowSet;
-use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::nll::ToRegionVid;
-use crate::borrow_check::nll::facts::AllFacts;
-use crate::borrow_check::nll::region_infer::values::LivenessValues;
-use crate::borrow_check::places_conflict;
 use rustc::infer::InferCtxt;
 use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
@@ -15,6 +9,15 @@
 use rustc::ty::{self, RegionVid, Ty};
 use rustc::ty::subst::SubstsRef;
 
+use crate::borrow_check::{
+    borrow_set::BorrowSet,
+    location::LocationTable,
+    nll::ToRegionVid,
+    facts::AllFacts,
+    region_infer::values::LivenessValues,
+    places_conflict,
+};
+
 pub(super) fn generate_constraints<'cx, 'tcx>(
     infcx: &InferCtxt<'cx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -97,6 +100,7 @@
         location: Location,
     ) {
         if let Some(all_facts) = self.all_facts {
+            let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
             all_facts.cfg_edge.push((
                 self.location_table.start_index(location),
                 self.location_table.mid_index(location),
@@ -142,6 +146,7 @@
         location: Location,
     ) {
         if let Some(all_facts) = self.all_facts {
+            let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
             all_facts.cfg_edge.push((
                 self.location_table.start_index(location),
                 self.location_table.mid_index(location),
@@ -205,6 +210,8 @@
     /// as `killed`. For example, when assigning to a local, or on a call's return destination.
     fn record_killed_borrows_for_place(&mut self, place: &Place<'tcx>, location: Location) {
         if let Some(all_facts) = self.all_facts {
+            let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
+
             // Depending on the `Place` we're killing:
             // - if it's a local, or a single deref of a local,
             //   we kill all the borrows on the local.
diff --git a/src/librustc_mir/borrow_check/nll/constraints/graph.rs b/src/librustc_mir/borrow_check/constraints/graph.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/nll/constraints/graph.rs
rename to src/librustc_mir/borrow_check/constraints/graph.rs
index b6a9a7e..3e7aa67 100644
--- a/src/librustc_mir/borrow_check/nll/constraints/graph.rs
+++ b/src/librustc_mir/borrow_check/constraints/graph.rs
@@ -1,12 +1,15 @@
-use crate::borrow_check::nll::type_check::Locations;
-use crate::borrow_check::nll::constraints::OutlivesConstraintIndex;
-use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConstraint};
 use rustc::mir::ConstraintCategory;
 use rustc::ty::RegionVid;
 use rustc_data_structures::graph;
 use rustc_index::vec::IndexVec;
 use syntax_pos::DUMMY_SP;
 
+use crate::borrow_check::{
+    type_check::Locations,
+    constraints::OutlivesConstraintIndex,
+    constraints::{OutlivesConstraintSet, OutlivesConstraint},
+};
+
 /// The construct graph organizes the constraints by their end-points.
 /// It can be used to view a `R1: R2` constraint as either an edge `R1
 /// -> R2` or `R2 -> R1` depending on the direction type `D`.
diff --git a/src/librustc_mir/borrow_check/nll/constraints/mod.rs b/src/librustc_mir/borrow_check/constraints/mod.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/nll/constraints/mod.rs
rename to src/librustc_mir/borrow_check/constraints/mod.rs
index 8a242b7..96982b6 100644
--- a/src/librustc_mir/borrow_check/nll/constraints/mod.rs
+++ b/src/librustc_mir/borrow_check/constraints/mod.rs
@@ -1,4 +1,3 @@
-use crate::borrow_check::nll::type_check::Locations;
 use rustc::mir::ConstraintCategory;
 use rustc::ty::RegionVid;
 use rustc_data_structures::graph::scc::Sccs;
@@ -6,6 +5,8 @@
 use std::fmt;
 use std::ops::Index;
 
+use crate::borrow_check::type_check::Locations;
+
 crate mod graph;
 
 /// A set of NLL region constraints. These include "outlives"
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/conflict_errors.rs
rename to src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index b1e327c..1cd43d4 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -14,18 +14,22 @@
 use syntax_pos::Span;
 use syntax::source_map::DesugaringKind;
 
-use super::nll::explain_borrow::BorrowExplanation;
-use super::nll::region_infer::{RegionName, RegionNameSource};
-use super::prefixes::IsPrefixOf;
-use super::WriteKind;
-use super::borrow_set::BorrowData;
-use super::MirBorrowckCtxt;
-use super::{InitializationRequiringAction, PrefixSet};
-use super::error_reporting::{IncludingDowncast, UseSpans};
 use crate::dataflow::drop_flag_effects;
 use crate::dataflow::indexes::{MovePathIndex, MoveOutIndex};
 use crate::util::borrowck_errors;
 
+use crate::borrow_check::{
+    prefixes::IsPrefixOf,
+    WriteKind,
+    borrow_set::BorrowData,
+    MirBorrowckCtxt, InitializationRequiringAction, PrefixSet
+};
+
+use super::{
+    IncludingDowncast, UseSpans, RegionName, RegionNameSource,
+    explain_borrow::BorrowExplanation,
+};
+
 #[derive(Debug)]
 struct MoveSite {
     /// Index of the "move out" that we found. The `MoveData` can
@@ -46,7 +50,7 @@
 }
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
-    pub(super) fn report_use_of_moved_or_uninitialized(
+    pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
@@ -74,10 +78,7 @@
             .collect();
 
         if move_out_indices.is_empty() {
-            let root_place = self
-                .prefixes(used_place, PrefixSet::All)
-                .last()
-                .unwrap();
+            let root_place = PlaceRef { projection: &[], ..used_place };
 
             if !self.uninitialized_error_reported.insert(root_place) {
                 debug!(
@@ -236,15 +237,17 @@
                     let tcx = self.infcx.tcx;
                     let generics = tcx.generics_of(self.mir_def_id);
                     let param = generics.type_param(&param_ty, tcx);
-                    let generics = tcx.hir().get_generics(self.mir_def_id).unwrap();
-                    suggest_constraining_type_param(
-                        generics,
-                        &mut err,
-                        &param.name.as_str(),
-                        "Copy",
-                        tcx.sess.source_map(),
-                        span,
-                    );
+                    if let Some(generics) =
+                        tcx.hir().get_generics(tcx.closure_base_def_id(self.mir_def_id)) {
+                        suggest_constraining_type_param(
+                            generics,
+                            &mut err,
+                            &param.name.as_str(),
+                            "Copy",
+                            tcx.sess.source_map(),
+                            span,
+                        );
+                    }
                 }
                 let span = if let Some(local) = place.as_local() {
                     let decl = &self.body.local_decls[local];
@@ -269,7 +272,7 @@
         }
     }
 
-    pub(super) fn report_move_out_while_borrowed(
+    pub(in crate::borrow_check) fn report_move_out_while_borrowed(
         &mut self,
         location: Location,
         (place, span): (&Place<'tcx>, Span),
@@ -326,7 +329,7 @@
         err.buffer(&mut self.errors_buffer);
     }
 
-    pub(super) fn report_use_while_mutably_borrowed(
+    pub(in crate::borrow_check) fn report_use_while_mutably_borrowed(
         &mut self,
         location: Location,
         (place, _span): (&Place<'tcx>, Span),
@@ -368,7 +371,7 @@
         err
     }
 
-    pub(super) fn report_conflicting_borrow(
+    pub(in crate::borrow_check) fn report_conflicting_borrow(
         &mut self,
         location: Location,
         (place, span): (&Place<'tcx>, Span),
@@ -614,7 +617,7 @@
     ///
     /// >  cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as
     /// >  mutable (via `a.u.s.b`) [E0502]
-    pub(super) fn describe_place_for_conflicting_borrow(
+    pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow(
         &self,
         first_borrowed_place: &Place<'tcx>,
         second_borrowed_place: &Place<'tcx>,
@@ -722,7 +725,7 @@
     /// short a lifetime. (But sometimes it is more useful to report
     /// it as a more direct conflict between the execution of a
     /// `Drop::drop` with an aliasing borrow.)
-    pub(super) fn report_borrowed_value_does_not_live_long_enough(
+    pub(in crate::borrow_check) fn report_borrowed_value_does_not_live_long_enough(
         &mut self,
         location: Location,
         borrow: &BorrowData<'tcx>,
@@ -1478,7 +1481,7 @@
         result
     }
 
-    pub(super) fn report_illegal_mutation_of_borrowed(
+    pub(in crate::borrow_check) fn report_illegal_mutation_of_borrowed(
         &mut self,
         location: Location,
         (place, span): (&Place<'tcx>, Span),
@@ -1537,7 +1540,7 @@
     /// assigned; `err_place` is a place providing a reason why
     /// `place` is not mutable (e.g., the non-`mut` local `x` in an
     /// assignment to `x.f`).
-    pub(super) fn report_illegal_reassignment(
+    pub(in crate::borrow_check) fn report_illegal_reassignment(
         &mut self,
         _location: Location,
         (place, span): (&Place<'tcx>, Span),
@@ -2080,7 +2083,7 @@
 impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
     /// Annotate the provided diagnostic with information about borrow from the fn signature that
     /// helps explain.
-    pub(super) fn emit(
+    pub(in crate::borrow_check) fn emit(
         &self,
         cx: &mut MirBorrowckCtxt<'_, 'tcx>,
         diag: &mut DiagnosticBuilder<'_>,
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
rename to src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
index 43aabac..a463d2c 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
@@ -1,10 +1,7 @@
+//! Print diagnostics to explain why values are borrowed.
+
 use std::collections::VecDeque;
 
-use crate::borrow_check::borrow_set::BorrowData;
-use crate::borrow_check::error_reporting::UseSpans;
-use crate::borrow_check::nll::region_infer::{Cause, RegionName};
-use crate::borrow_check::nll::ConstraintDescription;
-use crate::borrow_check::{MirBorrowckCtxt, WriteKind};
 use rustc::mir::{
     CastKind, ConstraintCategory, FakeReadCause, Local, Location, Body, Operand, Place, Rvalue,
     Statement, StatementKind, TerminatorKind,
@@ -17,7 +14,14 @@
 use syntax_pos::Span;
 use syntax_pos::symbol::Symbol;
 
-mod find_use;
+use crate::borrow_check::{
+    borrow_set::BorrowData,
+    region_infer::Cause,
+    nll::ConstraintDescription,
+    MirBorrowckCtxt, WriteKind,
+};
+
+use super::{UseSpans, find_use, RegionName};
 
 #[derive(Debug)]
 pub(in crate::borrow_check) enum BorrowExplanation {
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs b/src/librustc_mir/borrow_check/diagnostics/find_use.rs
similarity index 96%
rename from src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
rename to src/librustc_mir/borrow_check/diagnostics/find_use.rs
index 7ab0692..c557e52 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/find_use.rs
@@ -1,8 +1,7 @@
 use std::collections::VecDeque;
 use std::rc::Rc;
 
-use crate::borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
-use crate::borrow_check::nll::ToRegionVid;
+use crate::borrow_check::{nll::ToRegionVid, region_infer::{Cause, RegionInferenceContext}};
 use crate::util::liveness::{self, DefUse};
 use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
 use rustc::mir::{Local, Location, Body};
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/error_reporting.rs
rename to src/librustc_mir/borrow_check/diagnostics/mod.rs
index 9953d28..1a76265 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -1,3 +1,5 @@
+//! Borrow checker diagnostics.
+
 use rustc::hir;
 use rustc::hir::def::Namespace;
 use rustc::hir::def_id::DefId;
@@ -17,6 +19,22 @@
 use super::MirBorrowckCtxt;
 use crate::dataflow::move_paths::{InitLocation, LookupResult};
 
+mod find_use;
+mod var_name;
+mod region_name;
+mod outlives_suggestion;
+
+mod conflict_errors;
+mod move_errors;
+mod mutability_errors;
+mod region_errors;
+mod explain_borrow;
+
+crate use mutability_errors::AccessKind;
+crate use region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
+crate use region_errors::{ErrorReportingCtx, ErrorConstraintInfo};
+crate use outlives_suggestion::OutlivesSuggestionBuilder;
+
 pub(super) struct IncludingDowncast(pub(super) bool);
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/move_errors.rs
rename to src/librustc_mir/borrow_check/diagnostics/move_errors.rs
index fd77976..cc63410 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
@@ -5,7 +5,7 @@
 
 use crate::borrow_check::MirBorrowckCtxt;
 use crate::borrow_check::prefixes::PrefixSet;
-use crate::borrow_check::error_reporting::UseSpans;
+use crate::borrow_check::diagnostics::UseSpans;
 use crate::dataflow::move_paths::{
     IllegalMoveOrigin, IllegalMoveOriginKind,
     LookupResult, MoveError, MovePathIndex,
@@ -223,18 +223,24 @@
 
     fn report(&mut self, error: GroupedMoveError<'tcx>) {
         let (mut err, err_span) = {
-            let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind<'_>) =
+            let (span, use_spans, original_path, kind,):
+            (
+                Span,
+                Option<UseSpans>,
+                &Place<'tcx>,
+                &IllegalMoveOriginKind<'_>,
+            ) =
                 match error {
                     GroupedMoveError::MovesFromPlace { span, ref original_path, ref kind, .. } |
                     GroupedMoveError::MovesFromValue { span, ref original_path, ref kind, .. } => {
-                        (span, original_path, kind)
+                        (span, None, original_path, kind)
                     }
                     GroupedMoveError::OtherIllegalMove {
                         use_spans,
                         ref original_path,
                         ref kind
                     } => {
-                        (use_spans.args_or_use(), original_path, kind)
+                        (use_spans.args_or_use(), Some(use_spans), original_path, kind)
                     },
                 };
             debug!("report: original_path={:?} span={:?}, kind={:?} \
@@ -250,6 +256,7 @@
                             original_path,
                             target_place,
                             span,
+                            use_spans,
                         )
                     }
                     IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
@@ -296,6 +303,7 @@
         move_place: &Place<'tcx>,
         deref_target_place: &Place<'tcx>,
         span: Span,
+        use_spans: Option<UseSpans>,
     ) -> DiagnosticBuilder<'a> {
         // Inspect the type of the content behind the
         // borrow to provide feedback about why this
@@ -416,7 +424,7 @@
         if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
             let is_option = move_ty.starts_with("std::option::Option");
             let is_result = move_ty.starts_with("std::result::Result");
-            if is_option || is_result {
+            if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
                 err.span_suggestion(
                     span,
                     &format!("consider borrowing the `{}`'s content", if is_option {
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/mutability_errors.rs
rename to src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index 98a7b10..016a319 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -1,6 +1,6 @@
 use rustc::hir;
 use rustc::hir::Node;
-use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyCache};
+use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyAndCache};
 use rustc::mir::{Mutability, Place, PlaceRef, PlaceBase, ProjectionElem};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_index::vec::Idx;
@@ -8,18 +8,18 @@
 use syntax_pos::symbol::kw;
 
 use crate::borrow_check::MirBorrowckCtxt;
-use crate::borrow_check::error_reporting::BorrowedContentSource;
+use crate::borrow_check::diagnostics::BorrowedContentSource;
 use crate::util::collect_writes::FindAssignments;
 use rustc_errors::Applicability;
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub(super) enum AccessKind {
+pub(crate) enum AccessKind {
     MutableBorrow,
     Mutate,
 }
 
 impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
-    pub(super) fn report_mutability_error(
+    pub(crate) fn report_mutability_error(
         &mut self,
         access_place: &Place<'tcx>,
         span: Span,
@@ -533,7 +533,7 @@
 // by trying (3.), then (2.) and finally falling back on (1.).
 fn suggest_ampmut<'tcx>(
     tcx: TyCtxt<'tcx>,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
     local: Local,
     local_decl: &mir::LocalDecl<'tcx>,
     opt_ty_info: Option<Span>,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs
rename to src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
index 938059c..b61c37b 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/outlives_suggestion.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
@@ -13,12 +13,10 @@
 
 use smallvec::SmallVec;
 
-use crate::borrow_check::nll::region_infer::{
-    error_reporting::{
-        region_name::{RegionName, RegionNameSource},
-        ErrorConstraintInfo, ErrorReportingCtx, RegionErrorNamingCtx,
-    },
-    RegionInferenceContext,
+use crate::borrow_check::region_infer::RegionInferenceContext;
+
+use super::{
+    RegionName, RegionNameSource, ErrorConstraintInfo, ErrorReportingCtx, RegionErrorNamingCtx,
 };
 
 /// The different things we could suggest.
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
similarity index 96%
rename from src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
rename to src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 5e79a2f..8a37e2d 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -1,10 +1,5 @@
-use crate::borrow_check::nll::constraints::OutlivesConstraint;
-use crate::borrow_check::nll::region_infer::RegionInferenceContext;
-use crate::borrow_check::nll::type_check::Locations;
-use crate::borrow_check::nll::universal_regions::DefiningTy;
-use crate::borrow_check::nll::ConstraintDescription;
-use crate::borrow_check::Upvar;
-use crate::util::borrowck_errors;
+//! Error reporting machinery for lifetime errors.
+
 use rustc::hir::def_id::DefId;
 use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc::infer::InferCtxt;
@@ -19,14 +14,18 @@
 use syntax_pos::Span;
 use syntax_pos::symbol::Symbol;
 
-use self::outlives_suggestion::OutlivesSuggestionBuilder;
+use crate::util::borrowck_errors;
 
-pub mod outlives_suggestion;
+use crate::borrow_check::{
+    constraints::OutlivesConstraint,
+    region_infer::RegionInferenceContext,
+    type_check::Locations,
+    universal_regions::DefiningTy,
+    nll::ConstraintDescription,
+    Upvar,
+};
 
-mod region_name;
-mod var_name;
-
-crate use self::region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
+use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource, RegionErrorNamingCtx};
 
 impl ConstraintDescription for ConstraintCategory {
     fn description(&self) -> &'static str {
@@ -61,36 +60,36 @@
 /// Various pieces of state used when reporting borrow checker errors.
 pub struct ErrorReportingCtx<'a, 'b, 'tcx> {
     /// The region inference context used for borrow chekcing this MIR body.
-    region_infcx: &'b RegionInferenceContext<'tcx>,
+    pub(super) region_infcx: &'b RegionInferenceContext<'tcx>,
 
     /// The inference context used for type checking.
-    infcx: &'b InferCtxt<'a, 'tcx>,
+    pub(super) infcx: &'b InferCtxt<'a, 'tcx>,
 
     /// The MIR def we are reporting errors on.
-    mir_def_id: DefId,
+    pub(super) mir_def_id: DefId,
 
     /// The MIR body we are reporting errors on (for convenience).
-    body: &'b Body<'tcx>,
+    pub(super) body: &'b Body<'tcx>,
 
     /// User variable names for MIR locals (where applicable).
-    local_names: &'b IndexVec<Local, Option<Symbol>>,
+    pub(super) local_names: &'b IndexVec<Local, Option<Symbol>>,
 
     /// Any upvars for the MIR body we have kept track of during borrow checking.
-    upvars: &'b [Upvar],
+    pub(super) upvars: &'b [Upvar],
 }
 
 /// Information about the various region constraints involved in a borrow checker error.
 #[derive(Clone, Debug)]
 pub struct ErrorConstraintInfo {
     // fr: outlived_fr
-    fr: RegionVid,
-    fr_is_local: bool,
-    outlived_fr: RegionVid,
-    outlived_fr_is_local: bool,
+    pub(super) fr: RegionVid,
+    pub(super) fr_is_local: bool,
+    pub(super) outlived_fr: RegionVid,
+    pub(super) outlived_fr_is_local: bool,
 
     // Category and span for best blame constraint
-    category: ConstraintCategory,
-    span: Span,
+    pub(super) category: ConstraintCategory,
+    pub(super) span: Span,
 }
 
 impl<'tcx> RegionInferenceContext<'tcx> {
@@ -368,7 +367,7 @@
     /// ```
     ///
     /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
-    pub(super) fn report_error<'a>(
+    pub(in crate::borrow_check) fn report_error<'a>(
         &'a self,
         body: &Body<'tcx>,
         local_names: &IndexVec<Local, Option<Symbol>>,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
rename to src/librustc_mir/borrow_check/diagnostics/region_name.rs
index 0f5d1c5..720c77b 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
@@ -1,12 +1,5 @@
 use std::fmt::{self, Display};
 
-use crate::borrow_check::nll::region_infer::{
-    RegionInferenceContext,
-    error_reporting::ErrorReportingCtx,
-};
-use crate::borrow_check::nll::universal_regions::DefiningTy;
-use crate::borrow_check::nll::ToRegionVid;
-use crate::borrow_check::Upvar;
 use rustc::hir;
 use rustc::hir::def::{Res, DefKind};
 use rustc::hir::def_id::DefId;
@@ -21,6 +14,14 @@
 use rustc_data_structures::fx::FxHashMap;
 use syntax_pos::{Span, symbol::Symbol, DUMMY_SP};
 
+use crate::borrow_check::{
+    diagnostics::region_errors::ErrorReportingCtx,
+    region_infer::RegionInferenceContext,
+    universal_regions::DefiningTy,
+    nll::ToRegionVid,
+    Upvar,
+};
+
 /// A name for a particular region used in emitting diagnostics. This name could be a generated
 /// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
 #[derive(Debug, Clone)]
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs b/src/librustc_mir/borrow_check/diagnostics/var_name.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
rename to src/librustc_mir/borrow_check/diagnostics/var_name.rs
index 1ac44c4..839e09b 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/var_name.rs
@@ -1,5 +1,4 @@
-use crate::borrow_check::nll::region_infer::RegionInferenceContext;
-use crate::borrow_check::nll::ToRegionVid;
+use crate::borrow_check::{nll::ToRegionVid, region_infer::RegionInferenceContext};
 use crate::borrow_check::Upvar;
 use rustc::mir::{Local, Body};
 use rustc::ty::{RegionVid, TyCtxt};
diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/facts.rs
similarity index 91%
rename from src/librustc_mir/borrow_check/nll/facts.rs
rename to src/librustc_mir/borrow_check/facts.rs
index 13e5769..a16c36d 100644
--- a/src/librustc_mir/borrow_check/nll/facts.rs
+++ b/src/librustc_mir/borrow_check/facts.rs
@@ -1,6 +1,6 @@
 use crate::borrow_check::location::{LocationIndex, LocationTable};
 use crate::dataflow::indexes::{BorrowIndex, MovePathIndex};
-use polonius_engine::AllFacts as PoloniusAllFacts;
+use polonius_engine::AllFacts as PoloniusFacts;
 use polonius_engine::Atom;
 use rustc::mir::Local;
 use rustc::ty::{RegionVid, TyCtxt};
@@ -11,7 +11,18 @@
 use std::io::Write;
 use std::path::Path;
 
-crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex, Local, MovePathIndex>;
+#[derive(Copy, Clone, Debug)]
+crate struct RustcFacts;
+
+impl polonius_engine::FactTypes for RustcFacts {
+    type Origin = RegionVid;
+    type Loan = BorrowIndex;
+    type Point = LocationIndex;
+    type Variable = Local;
+    type Path = MovePathIndex;
+}
+
+crate type AllFacts = PoloniusFacts<RustcFacts>;
 
 crate trait AllFactsExt {
     /// Returns `true` if there is a need to gather `AllFacts` given the
@@ -55,6 +66,7 @@
             wr.write_facts_to_path(self.[
                 borrow_region,
                 universal_region,
+                placeholder,
                 cfg_edge,
                 killed,
                 outlives,
@@ -69,6 +81,7 @@
                 initialized_at,
                 moved_out_at,
                 path_accessed_at,
+                known_subset,
             ])
         }
         Ok(())
diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs
index ce5d2a1..57c544f 100644
--- a/src/librustc_mir/borrow_check/flows.rs
+++ b/src/librustc_mir/borrow_check/flows.rs
@@ -3,16 +3,15 @@
 //! FIXME: this might be better as a "generic" fixed-point combinator,
 //! but is not as ugly as it is right now.
 
-use rustc::mir::{BasicBlock, Local, Location};
-use rustc::ty::RegionVid;
+use rustc::mir::{BasicBlock, Location};
 use rustc_index::bit_set::BitIter;
 
 use crate::borrow_check::location::LocationIndex;
 
-use polonius_engine::Output;
+use crate::borrow_check::nll::PoloniusOutput;
 
 use crate::dataflow::indexes::BorrowIndex;
-use crate::dataflow::move_paths::{HasMoveData, MovePathIndex};
+use crate::dataflow::move_paths::HasMoveData;
 use crate::dataflow::Borrows;
 use crate::dataflow::EverInitializedPlaces;
 use crate::dataflow::MaybeUninitializedPlaces;
@@ -21,8 +20,6 @@
 use std::fmt;
 use std::rc::Rc;
 
-crate type PoloniusOutput = Output<RegionVid, BorrowIndex, LocationIndex, Local, MovePathIndex>;
-
 crate struct Flows<'b, 'tcx> {
     borrows: FlowAtLocation<'tcx, Borrows<'b, 'tcx>>,
     pub uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'tcx>>,
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs
similarity index 96%
rename from src/librustc_mir/borrow_check/nll/invalidation.rs
rename to src/librustc_mir/borrow_check/invalidation.rs
index 98679f2..58fac55 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/invalidation.rs
@@ -1,28 +1,28 @@
-use crate::borrow_check::borrow_set::BorrowSet;
-use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::{JustWrite, WriteAndRead};
-use crate::borrow_check::{AccessDepth, Deep, Shallow};
-use crate::borrow_check::{ReadOrWrite, Activation, Read, Reservation, Write};
-use crate::borrow_check::{LocalMutationIsAllowed, MutateMode};
-use crate::borrow_check::ArtificialField;
-use crate::borrow_check::{ReadKind, WriteKind};
-use crate::borrow_check::nll::facts::AllFacts;
-use crate::borrow_check::path_utils::*;
-use crate::dataflow::indexes::BorrowIndex;
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyCache, Rvalue};
+use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyAndCache, Rvalue};
 use rustc::mir::{Statement, StatementKind};
 use rustc::mir::TerminatorKind;
 use rustc::mir::{Operand, BorrowKind};
 use rustc_data_structures::graph::dominators::Dominators;
 
+use crate::dataflow::indexes::BorrowIndex;
+
+use crate::borrow_check::{
+    borrow_set::BorrowSet,
+    location::LocationTable,
+    facts::AllFacts,
+    path_utils::*,
+    JustWrite, WriteAndRead, AccessDepth, Deep, Shallow, ReadOrWrite, Activation, Read,
+    Reservation, Write, LocalMutationIsAllowed, MutateMode, ArtificialField, ReadKind, WriteKind,
+};
+
 pub(super) fn generate_invalidates<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     all_facts: &mut Option<AllFacts>,
     location_table: &LocationTable,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
     borrow_set: &BorrowSet<'tcx>,
 ) {
     if all_facts.is_none() {
@@ -31,6 +31,7 @@
     }
 
     if let Some(all_facts) = all_facts {
+        let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
         let dominators = body.dominators();
         let mut ig = InvalidationGenerator {
             all_facts,
diff --git a/src/librustc_mir/borrow_check/nll/member_constraints.rs b/src/librustc_mir/borrow_check/member_constraints.rs
similarity index 100%
rename from src/librustc_mir/borrow_check/nll/member_constraints.rs
rename to src/librustc_mir/borrow_check/member_constraints.rs
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index bacff0b..11012ef 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1,6 +1,5 @@
 //! This query borrow-checks the MIR to (further) ensure it is not broken.
 
-use crate::borrow_check::nll::region_infer::RegionInferenceContext;
 use rustc::hir::{self, HirId};
 use rustc::hir::Node;
 use rustc::hir::def_id::DefId;
@@ -9,8 +8,8 @@
 use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT};
 use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc::mir::{
-    ClearCrossCrate, Local, Location, Body, BodyCache, Mutability, Operand, Place, PlaceBase,
-    PlaceElem, PlaceRef, ReadOnlyBodyCache, Static, StaticKind, read_only
+    ClearCrossCrate, Local, Location, Body, BodyAndCache, Mutability, Operand, Place, PlaceBase,
+    PlaceElem, PlaceRef, ReadOnlyBodyAndCache, Static, StaticKind, read_only
 };
 use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
@@ -41,29 +40,39 @@
 use crate::dataflow::EverInitializedPlaces;
 use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 
-use self::borrow_set::{BorrowData, BorrowSet};
 use self::flows::Flows;
 use self::location::LocationTable;
 use self::prefixes::PrefixSet;
 use self::MutateMode::{JustWrite, WriteAndRead};
-use self::mutability_errors::AccessKind;
+use self::diagnostics::AccessKind;
 
 use self::path_utils::*;
 
-crate mod borrow_set;
-mod error_reporting;
+mod diagnostics;
 mod flows;
 mod location;
-mod conflict_errors;
-mod move_errors;
-mod mutability_errors;
 mod path_utils;
-crate mod place_ext;
-crate mod places_conflict;
 mod prefixes;
 mod used_muts;
+mod constraint_generation;
+mod facts;
+mod invalidation;
+mod renumber;
+mod member_constraints;
+mod constraints;
+mod universal_regions;
+mod type_check;
+mod region_infer;
+mod borrow_set;
+mod place_ext;
+mod places_conflict;
+mod nll;
 
-pub(crate) mod nll;
+crate use region_infer::RegionInferenceContext;
+crate use borrow_set::{BorrowSet, BorrowData};
+crate use places_conflict::{places_conflict, PlaceConflictBias};
+crate use place_ext::PlaceExt;
+crate use nll::ToRegionVid;
 
 // FIXME(eddyb) perhaps move this somewhere more centrally.
 #[derive(Debug)]
@@ -102,7 +111,7 @@
 fn do_mir_borrowck<'a, 'tcx>(
     infcx: &InferCtxt<'a, 'tcx>,
     input_body: &Body<'tcx>,
-    input_promoted: &IndexVec<Promoted, BodyCache<'tcx>>,
+    input_promoted: &IndexVec<Promoted, BodyAndCache<'tcx>>,
     def_id: DefId,
 ) -> BorrowCheckResult<'tcx> {
     debug!("do_mir_borrowck(def_id = {:?})", def_id);
@@ -164,7 +173,7 @@
     // will have a lifetime tied to the inference context.
     let body_clone: Body<'tcx> = input_body.clone();
     let mut promoted = input_promoted.clone();
-    let mut body = BodyCache::new(body_clone);
+    let mut body = BodyAndCache::new(body_clone);
     let free_regions =
         nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted);
     let body = read_only!(body); // no further changes
@@ -177,7 +186,7 @@
 
     let mut errors_buffer = Vec::new();
     let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<(Place<'tcx>, MoveError<'tcx>)>>) =
-        match MoveData::gather_moves(&body, tcx) {
+        match MoveData::gather_moves(&body, tcx, param_env) {
             Ok(move_data) => (move_data, None),
             Err((move_data, move_errors)) => (move_data, Some(move_errors)),
         };
@@ -405,7 +414,7 @@
 
 crate struct MirBorrowckCtxt<'cx, 'tcx> {
     crate infcx: &'cx InferCtxt<'cx, 'tcx>,
-    body: ReadOnlyBodyCache<'cx, 'tcx>,
+    body: ReadOnlyBodyAndCache<'cx, 'tcx>,
     mir_def_id: DefId,
     param_env: ty::ParamEnv<'tcx>,
     move_data: &'cx MoveData<'tcx>,
@@ -496,7 +505,7 @@
     type FlowState = Flows<'cx, 'tcx>;
 
     fn body(&self) -> &'cx Body<'tcx> {
-        self.body.body()
+        *self.body
     }
 
     fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) {
@@ -1603,7 +1612,6 @@
                         (prefix, place_span.0, place_span.1),
                         mpi,
                     );
-                    return; // don't bother finding other problems.
                 }
             }
             Err(NoMovePathFound::ReachedStatic) => {
@@ -1617,6 +1625,46 @@
         }
     }
 
+    /// Subslices correspond to multiple move paths, so we iterate through the
+    /// elements of the base array. For each element we check
+    ///
+    /// * Does this element overlap with our slice.
+    /// * Is any part of it uninitialized.
+    fn check_if_subslice_element_is_moved(
+        &mut self,
+        location: Location,
+        desired_action: InitializationRequiringAction,
+        place_span: (PlaceRef<'cx, 'tcx>, Span),
+        maybe_uninits: &FlowAtLocation<'tcx, MaybeUninitializedPlaces<'cx, 'tcx>>,
+        from: u32,
+        to: u32,
+    ) {
+        if let Some(mpi) = self.move_path_for_place(place_span.0) {
+            let mut child = self.move_data.move_paths[mpi].first_child;
+            while let Some(child_mpi) = child {
+                let child_move_place = &self.move_data.move_paths[child_mpi];
+                let child_place = &child_move_place.place;
+                let last_proj = child_place.projection.last().unwrap();
+                if let ProjectionElem::ConstantIndex { offset, from_end, .. } = last_proj {
+                    debug_assert!(!from_end, "Array constant indexing shouldn't be `from_end`.");
+
+                    if (from..to).contains(offset) {
+                        if let Some(uninit_child) = maybe_uninits.has_any_child_of(child_mpi) {
+                            self.report_use_of_moved_or_uninitialized(
+                                location,
+                                desired_action,
+                                (place_span.0, place_span.0, place_span.1),
+                                uninit_child,
+                            );
+                            return; // don't bother finding other problems.
+                        }
+                    }
+                }
+                child = child_move_place.next_sibling;
+            }
+        }
+    }
+
     fn check_if_path_or_subpath_is_moved(
         &mut self,
         location: Location,
@@ -1643,6 +1691,30 @@
 
         self.check_if_full_path_is_moved(location, desired_action, place_span, flow_state);
 
+        if let [
+            base_proj @ ..,
+            ProjectionElem::Subslice { from, to, from_end: false },
+        ] = place_span.0.projection {
+            let place_ty = Place::ty_from(
+                place_span.0.base,
+                base_proj,
+                self.body(),
+                self.infcx.tcx,
+            );
+            if let ty::Array(..) = place_ty.ty.kind {
+                let array_place = PlaceRef { base: place_span.0.base, projection: base_proj };
+                self.check_if_subslice_element_is_moved(
+                    location,
+                    desired_action,
+                    (array_place, place_span.1),
+                    maybe_uninits,
+                    *from,
+                    *to,
+                );
+                return;
+            }
+        }
+
         // A move of any shallow suffix of `place` also interferes
         // with an attempt to use `place`. This is scenario 3 above.
         //
@@ -1678,25 +1750,16 @@
     /// static variable, as we do not track those in the MoveData.
     fn move_path_closest_to(
         &mut self,
-        place: PlaceRef<'cx, 'tcx>,
+        place: PlaceRef<'_, 'tcx>,
     ) -> Result<(PlaceRef<'cx, 'tcx>, MovePathIndex), NoMovePathFound> {
-        let mut last_prefix = place.base;
-
-        for prefix in self.prefixes(place, PrefixSet::All) {
-            if let Some(mpi) = self.move_path_for_place(prefix) {
-                return Ok((prefix, mpi));
-            }
-
-            last_prefix = prefix.base;
-        }
-
-        match last_prefix {
-            PlaceBase::Local(_) => panic!("should have move path for every Local"),
-            PlaceBase::Static(_) => Err(NoMovePathFound::ReachedStatic),
+        match self.move_data.rev_lookup.find(place) {
+            LookupResult::Parent(Some(mpi))
+            | LookupResult::Exact(mpi) => Ok((self.move_data.move_paths[mpi].place.as_ref(), mpi)),
+            LookupResult::Parent(None) => Err(NoMovePathFound::ReachedStatic),
         }
     }
 
-    fn move_path_for_place(&mut self, place: PlaceRef<'cx, 'tcx>) -> Option<MovePathIndex> {
+    fn move_path_for_place(&mut self, place: PlaceRef<'_, 'tcx>) -> Option<MovePathIndex> {
         // If returns None, then there is no move path corresponding
         // to a direct owner of `place` (which means there is nothing
         // that borrowck tracks for its analysis).
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll.rs
similarity index 82%
rename from src/librustc_mir/borrow_check/nll/mod.rs
rename to src/librustc_mir/borrow_check/nll.rs
index 16182fe..6d28a8c 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -1,19 +1,10 @@
-use crate::borrow_check::borrow_set::BorrowSet;
-use crate::borrow_check::location::{LocationIndex, LocationTable};
-use crate::borrow_check::nll::facts::AllFactsExt;
-use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
-use crate::borrow_check::nll::region_infer::values::RegionValueElements;
-use crate::dataflow::indexes::BorrowIndex;
-use crate::dataflow::move_paths::{InitLocation, MoveData, MovePathIndex, InitKind};
-use crate::dataflow::FlowAtLocation;
-use crate::dataflow::MaybeInitializedPlaces;
-use crate::transform::MirSource;
-use crate::borrow_check::Upvar;
+//! The entry point of the NLL borrow checker.
+
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
 use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements,
-                 Local, Location, Body, BodyCache, LocalKind, BasicBlock,
-                 Promoted, ReadOnlyBodyCache};
+                 Local, Location, Body, BodyAndCache, LocalKind, BasicBlock,
+                 Promoted, ReadOnlyBodyAndCache};
 use rustc::ty::{self, RegionKind, RegionVid};
 use rustc_index::vec::IndexVec;
 use rustc_errors::Diagnostic;
@@ -28,24 +19,25 @@
 
 use self::mir_util::PassWhere;
 use polonius_engine::{Algorithm, Output};
+
 use crate::util as mir_util;
 use crate::util::pretty;
+use crate::dataflow::move_paths::{InitLocation, MoveData, InitKind};
+use crate::dataflow::FlowAtLocation;
+use crate::dataflow::MaybeInitializedPlaces;
+use crate::transform::MirSource;
 
-mod constraint_generation;
-pub mod explain_borrow;
-mod facts;
-mod invalidation;
-crate mod region_infer;
-mod renumber;
-crate mod type_check;
-mod universal_regions;
+use crate::borrow_check::{
+    borrow_set::BorrowSet,
+    location::LocationTable,
+    facts::{AllFacts, AllFactsExt, RustcFacts},
+    region_infer::{RegionInferenceContext, values::RegionValueElements},
+    universal_regions::UniversalRegions,
+    type_check::{self, MirTypeckResults, MirTypeckRegionConstraints},
+    Upvar, renumber, constraint_generation, invalidation,
+};
 
-mod constraints;
-mod member_constraints;
-
-use self::facts::AllFacts;
-use self::region_infer::RegionInferenceContext;
-use self::universal_regions::UniversalRegions;
+crate type PoloniusOutput = Output<RustcFacts>;
 
 /// Rewrites the regions in the MIR to use NLL variables, also
 /// scraping out the set of universal regions (e.g., region parameters)
@@ -55,8 +47,8 @@
     infcx: &InferCtxt<'cx, 'tcx>,
     def_id: DefId,
     param_env: ty::ParamEnv<'tcx>,
-    body: &mut BodyCache<'tcx>,
-    promoted: &mut IndexVec<Promoted, BodyCache<'tcx>>,
+    body: &mut BodyAndCache<'tcx>,
+    promoted: &mut IndexVec<Promoted, BodyAndCache<'tcx>>,
 ) -> UniversalRegions<'tcx> {
     debug!("replace_regions_in_mir(def_id={:?})", def_id);
 
@@ -158,8 +150,8 @@
     infcx: &InferCtxt<'cx, 'tcx>,
     def_id: DefId,
     universal_regions: UniversalRegions<'tcx>,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
-    promoted: &IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
+    promoted: &IndexVec<Promoted, ReadOnlyBodyAndCache<'_, 'tcx>>,
     local_names: &IndexVec<Local, Option<Symbol>>,
     upvars: &[Upvar],
     location_table: &LocationTable,
@@ -170,14 +162,10 @@
     errors_buffer: &mut Vec<Diagnostic>,
 ) -> (
     RegionInferenceContext<'tcx>,
-    Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex, Local, MovePathIndex>>>,
+    Option<Rc<PoloniusOutput>>,
     Option<ClosureRegionRequirements<'tcx>>,
 ) {
-    let mut all_facts = if AllFacts::enabled(infcx.tcx) {
-        Some(AllFacts::default())
-    } else {
-        None
-    };
+    let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
 
     let universal_regions = Rc::new(universal_regions);
 
@@ -204,10 +192,44 @@
     );
 
     if let Some(all_facts) = &mut all_facts {
+        let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation");
         all_facts
             .universal_region
             .extend(universal_regions.universal_regions());
         populate_polonius_move_facts(all_facts, move_data, location_table, &body);
+
+        // Emit universal regions facts, and their relations, for Polonius.
+        //
+        // 1: universal regions are modeled in Polonius as a pair:
+        // - the universal region vid itself.
+        // - a "placeholder loan" associated to this universal region. Since they don't exist in
+        //   the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
+        //   added to the existing number of loans, as if they succeeded them in the set.
+        //
+        let borrow_count = borrow_set.borrows.len();
+        debug!(
+            "compute_regions: polonius placeholders, num_universals={}, borrow_count={}",
+            universal_regions.len(),
+            borrow_count
+        );
+
+        for universal_region in universal_regions.universal_regions() {
+            let universal_region_idx = universal_region.index();
+            let placeholder_loan_idx = borrow_count + universal_region_idx;
+            all_facts.placeholder.push((universal_region, placeholder_loan_idx.into()));
+        }
+
+        // 2: the universal region relations `outlives` constraints are emitted as
+        //  `known_subset` facts.
+        for (fr1, fr2) in universal_region_relations.known_outlives() {
+            if fr1 != fr2 {
+                debug!(
+                    "compute_regions: emitting polonius `known_subset` fr1={:?}, fr2={:?}",
+                    fr1, fr2
+                );
+                all_facts.known_subset.push((*fr1, *fr2));
+            }
+        }
     }
 
     // Create the region inference context, taking ownership of the
@@ -269,9 +291,10 @@
 
         if infcx.tcx.sess.opts.debugging_opts.polonius {
             let algorithm = env::var("POLONIUS_ALGORITHM")
-                .unwrap_or_else(|_| String::from("Hybrid"));
+                .unwrap_or_else(|_| String::from("Naive"));
             let algorithm = Algorithm::from_str(&algorithm).unwrap();
             debug!("compute_regions: using polonius algorithm {:?}", algorithm);
+            let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis");
             Some(Rc::new(Output::compute(
                 &all_facts,
                 algorithm,
@@ -283,8 +306,15 @@
     });
 
     // Solve the region constraints.
-    let closure_region_requirements =
-        regioncx.solve(infcx, &body, local_names, upvars, def_id, errors_buffer);
+    let closure_region_requirements = regioncx.solve(
+        infcx,
+        &body,
+        local_names,
+        upvars,
+        def_id,
+        errors_buffer,
+        polonius_output.clone(),
+    );
 
     // Dump MIR results into a file, if that is enabled. This let us
     // write unit-tests, as well as helping with debugging.
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 87a431a..9245064f 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -503,34 +503,62 @@
                 Overlap::Disjoint
             }
         }
-        (ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false },
-         ProjectionElem::Subslice {from, .. })
-        | (ProjectionElem::Subslice {from, .. },
-            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false }) => {
-            if offset >= from {
-                debug!(
-                    "place_element_conflict: DISJOINT-OR-EQ-ARRAY-CONSTANT-INDEX-SUBSLICE");
+        (
+            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false },
+            ProjectionElem::Subslice { from, to, from_end: false }
+        )
+        | (
+            ProjectionElem::Subslice { from, to, from_end: false },
+            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false }
+        ) => {
+            if (from..to).contains(&offset) {
+                debug!("place_element_conflict: DISJOINT-OR-EQ-ARRAY-CONSTANT-INDEX-SUBSLICE");
                 Overlap::EqualOrDisjoint
             } else {
                 debug!("place_element_conflict: DISJOINT-ARRAY-CONSTANT-INDEX-SUBSLICE");
                 Overlap::Disjoint
             }
         }
-        (ProjectionElem::ConstantIndex { offset, min_length: _, from_end: true },
-         ProjectionElem::Subslice {from: _, to })
-        | (ProjectionElem::Subslice {from: _, to },
-            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: true }) => {
-            if offset > to {
-                debug!("place_element_conflict: \
-                       DISJOINT-OR-EQ-ARRAY-CONSTANT-INDEX-SUBSLICE-FE");
+        (ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false },
+         ProjectionElem::Subslice {from, .. })
+        | (ProjectionElem::Subslice {from, .. },
+            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false }) => {
+            if offset >= from {
+                debug!(
+                    "place_element_conflict: DISJOINT-OR-EQ-SLICE-CONSTANT-INDEX-SUBSLICE");
                 Overlap::EqualOrDisjoint
             } else {
-                debug!("place_element_conflict: DISJOINT-ARRAY-CONSTANT-INDEX-SUBSLICE-FE");
+                debug!("place_element_conflict: DISJOINT-SLICE-CONSTANT-INDEX-SUBSLICE");
                 Overlap::Disjoint
             }
         }
+        (ProjectionElem::ConstantIndex { offset, min_length: _, from_end: true },
+         ProjectionElem::Subslice { to, from_end: true, .. })
+        | (ProjectionElem::Subslice { to, from_end: true, .. },
+            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: true }) => {
+            if offset > to {
+                debug!("place_element_conflict: \
+                       DISJOINT-OR-EQ-SLICE-CONSTANT-INDEX-SUBSLICE-FE");
+                Overlap::EqualOrDisjoint
+            } else {
+                debug!("place_element_conflict: DISJOINT-SLICE-CONSTANT-INDEX-SUBSLICE-FE");
+                Overlap::Disjoint
+            }
+        }
+        (
+            ProjectionElem::Subslice { from: f1, to: t1, from_end: false },
+            ProjectionElem::Subslice { from: f2, to: t2, from_end: false }
+        ) => {
+            if f2 >= t1 || f1 >= t2 {
+                debug!("place_element_conflict: DISJOINT-ARRAY-SUBSLICES");
+                Overlap::Disjoint
+            } else {
+                debug!("place_element_conflict: DISJOINT-OR-EQ-ARRAY-SUBSLICES");
+                Overlap::EqualOrDisjoint
+            }
+        }
         (ProjectionElem::Subslice { .. }, ProjectionElem::Subslice { .. }) => {
-            debug!("place_element_conflict: DISJOINT-OR-EQ-ARRAY-SUBSLICES");
+            debug!("place_element_conflict: DISJOINT-OR-EQ-SLICE-SUBSLICES");
              Overlap::EqualOrDisjoint
         }
         (ProjectionElem::Deref, _)
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index b58bf73..248faa5 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -11,7 +11,7 @@
 
 use rustc::hir;
 use rustc::ty::{self, TyCtxt};
-use rustc::mir::{Place, PlaceBase, PlaceRef, ProjectionElem, ReadOnlyBodyCache};
+use rustc::mir::{Place, PlaceBase, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache};
 
 pub trait IsPrefixOf<'cx, 'tcx> {
     fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool;
@@ -26,7 +26,7 @@
 }
 
 pub(super) struct Prefixes<'cx, 'tcx> {
-    body: ReadOnlyBodyCache<'cx, 'tcx>,
+    body: ReadOnlyBodyAndCache<'cx, 'tcx>,
     tcx: TyCtxt<'tcx>,
     kind: PrefixSet,
     next: Option<PlaceRef<'cx, 'tcx>>,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/region_infer/dump_mir.rs
similarity index 100%
rename from src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
rename to src/librustc_mir/borrow_check/region_infer/dump_mir.rs
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/region_infer/graphviz.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
rename to src/librustc_mir/borrow_check/region_infer/graphviz.rs
index fdf2af9..29c6f32 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
+++ b/src/librustc_mir/borrow_check/region_infer/graphviz.rs
@@ -2,11 +2,12 @@
 //! libgraphviz traits, specialized to attaching borrowck analysis
 //! data to rendered labels.
 
-use super::*;
-use crate::borrow_check::nll::constraints::OutlivesConstraint;
 use std::borrow::Cow;
 use std::io::{self, Write};
 
+use super::*;
+use crate::borrow_check::constraints::OutlivesConstraint;
+
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Write out the region constraint graph.
     crate fn dump_graphviz_raw_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
similarity index 87%
rename from src/librustc_mir/borrow_check/nll/region_infer/mod.rs
rename to src/librustc_mir/borrow_check/region_infer/mod.rs
index bd9e97e..b6946e2 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -1,21 +1,5 @@
 use std::rc::Rc;
 
-use crate::borrow_check::nll::{
-    constraints::{
-        graph::NormalConstraintGraph,
-        ConstraintSccIndex,
-        OutlivesConstraint,
-        OutlivesConstraintSet,
-    },
-    member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
-    region_infer::values::{
-        PlaceholderIndices, RegionElement, ToElementIndex
-    },
-    region_infer::error_reporting::outlives_suggestion::OutlivesSuggestionBuilder,
-    type_check::{free_region_relations::UniversalRegionRelations, Locations},
-};
-use crate::borrow_check::Upvar;
-
 use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::QueryOutlivesConstraint;
 use rustc::infer::opaque_types;
@@ -38,13 +22,28 @@
 use syntax_pos::Span;
 use syntax_pos::symbol::Symbol;
 
-crate use self::error_reporting::{RegionName, RegionNameSource, RegionErrorNamingCtx};
-use self::values::{LivenessValues, RegionValueElements, RegionValues};
-use super::universal_regions::UniversalRegions;
-use super::ToRegionVid;
+use crate::borrow_check::{
+    constraints::{
+        graph::NormalConstraintGraph,
+        ConstraintSccIndex,
+        OutlivesConstraint,
+        OutlivesConstraintSet,
+    },
+    member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
+    region_infer::values::{
+        PlaceholderIndices, RegionElement, ToElementIndex, LivenessValues, RegionValueElements,
+        RegionValues,
+    },
+    type_check::{free_region_relations::UniversalRegionRelations, Locations},
+    diagnostics::{
+        OutlivesSuggestionBuilder, RegionErrorNamingCtx,
+    },
+    nll::{ToRegionVid, PoloniusOutput},
+    universal_regions::UniversalRegions,
+    Upvar,
+};
 
 mod dump_mir;
-mod error_reporting;
 mod graphviz;
 
 pub mod values;
@@ -54,48 +53,51 @@
     /// variables are identified by their index (`RegionVid`). The
     /// definition contains information about where the region came
     /// from as well as its final inferred value.
-    definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
+    pub(in crate::borrow_check) definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
 
     /// The liveness constraints added to each region. For most
     /// regions, these start out empty and steadily grow, though for
     /// each universally quantified region R they start out containing
     /// the entire CFG and `end(R)`.
-    liveness_constraints: LivenessValues<RegionVid>,
+    pub(in crate::borrow_check) liveness_constraints: LivenessValues<RegionVid>,
 
     /// The outlives constraints computed by the type-check.
-    constraints: Rc<OutlivesConstraintSet>,
+    pub(in crate::borrow_check) constraints: Rc<OutlivesConstraintSet>,
 
     /// The constraint-set, but in graph form, making it easy to traverse
     /// the constraints adjacent to a particular region. Used to construct
     /// the SCC (see `constraint_sccs`) and for error reporting.
-    constraint_graph: Rc<NormalConstraintGraph>,
+    pub(in crate::borrow_check) constraint_graph: Rc<NormalConstraintGraph>,
 
     /// The SCC computed from `constraints` and the constraint
     /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
     /// compute the values of each region.
-    constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
+    pub(in crate::borrow_check) constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
 
     /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B`
     /// exists if `B: A`. Computed lazilly.
-    rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
+    pub(in crate::borrow_check) rev_constraint_graph:
+        Option<Rc<VecGraph<ConstraintSccIndex>>>,
 
     /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
-    member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
+    pub(in crate::borrow_check) member_constraints:
+        Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
 
     /// Records the member constraints that we applied to each scc.
     /// This is useful for error reporting. Once constraint
     /// propagation is done, this vector is sorted according to
     /// `member_region_scc`.
-    member_constraints_applied: Vec<AppliedMemberConstraint>,
+    pub(in crate::borrow_check) member_constraints_applied: Vec<AppliedMemberConstraint>,
 
     /// Map closure bounds to a `Span` that should be used for error reporting.
-    closure_bounds_mapping:
+    pub(in crate::borrow_check) closure_bounds_mapping:
         FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
 
     /// Contains the minimum universe of any variable within the same
     /// SCC. We will ensure that no SCC contains values that are not
     /// visible from this index.
-    scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
+    pub(in crate::borrow_check) scc_universes:
+        IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
 
     /// Contains a "representative" from each SCC. This will be the
     /// minimal RegionVid belonging to that universe. It is used as a
@@ -104,23 +106,25 @@
     /// of its SCC and be sure that -- if they have the same repr --
     /// they *must* be equal (though not having the same repr does not
     /// mean they are unequal).
-    scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>,
+    pub(in crate::borrow_check) scc_representatives:
+        IndexVec<ConstraintSccIndex, ty::RegionVid>,
 
     /// The final inferred values of the region variables; we compute
     /// one value per SCC. To get the value for any given *region*,
     /// you first find which scc it is a part of.
-    scc_values: RegionValues<ConstraintSccIndex>,
+    pub(in crate::borrow_check) scc_values: RegionValues<ConstraintSccIndex>,
 
     /// Type constraints that we check after solving.
-    type_tests: Vec<TypeTest<'tcx>>,
+    pub(in crate::borrow_check) type_tests: Vec<TypeTest<'tcx>>,
 
     /// Information about the universally quantified regions in scope
     /// on this function.
-    universal_regions: Rc<UniversalRegions<'tcx>>,
+    pub (in crate::borrow_check) universal_regions: Rc<UniversalRegions<'tcx>>,
 
     /// Information about how the universally quantified regions in
     /// scope on this function relate to one another.
-    universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+    pub(in crate::borrow_check) universal_region_relations:
+        Rc<UniversalRegionRelations<'tcx>>,
 }
 
 /// Each time that `apply_member_constraint` is successful, it appends
@@ -132,38 +136,38 @@
 /// with `'R: 'O` where `'R` is the pick-region and `'O` is the
 /// minimal viable option.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
-struct AppliedMemberConstraint {
+pub(crate) struct AppliedMemberConstraint {
     /// The SCC that was affected. (The "member region".)
     ///
     /// The vector if `AppliedMemberConstraint` elements is kept sorted
     /// by this field.
-    member_region_scc: ConstraintSccIndex,
+    pub(in crate::borrow_check) member_region_scc: ConstraintSccIndex,
 
     /// The "best option" that `apply_member_constraint` found -- this was
     /// added as an "ad-hoc" lower-bound to `member_region_scc`.
-    min_choice: ty::RegionVid,
+    pub(in crate::borrow_check) min_choice: ty::RegionVid,
 
     /// The "member constraint index" -- we can find out details about
     /// the constraint from
     /// `set.member_constraints[member_constraint_index]`.
-    member_constraint_index: NllMemberConstraintIndex,
+    pub(in crate::borrow_check) member_constraint_index: NllMemberConstraintIndex,
 }
 
-struct RegionDefinition<'tcx> {
+pub(crate) struct RegionDefinition<'tcx> {
     /// What kind of variable is this -- a free region? existential
     /// variable? etc. (See the `NLLRegionVariableOrigin` for more
     /// info.)
-    origin: NLLRegionVariableOrigin,
+    pub(in crate::borrow_check) origin: NLLRegionVariableOrigin,
 
     /// Which universe is this region variable defined in? This is
     /// most often `ty::UniverseIndex::ROOT`, but when we encounter
     /// forall-quantifiers like `for<'a> { 'a = 'b }`, we would create
     /// the variable for `'a` in a fresh universe that extends ROOT.
-    universe: ty::UniverseIndex,
+    pub(in crate::borrow_check) universe: ty::UniverseIndex,
 
     /// If this is 'static or an early-bound region, then this is
     /// `Some(X)` where `X` is the name of the region.
-    external_name: Option<ty::Region<'tcx>>,
+    pub(in crate::borrow_check) external_name: Option<ty::Region<'tcx>>,
 }
 
 /// N.B., the variants in `Cause` are intentionally ordered. Lower
@@ -455,7 +459,9 @@
     /// Once region solving has completed, this function will return
     /// the member constraints that were applied to the value of a given
     /// region `r`. See `AppliedMemberConstraint`.
-    fn applied_member_constraints(&self, r: impl ToRegionVid) -> &[AppliedMemberConstraint] {
+    pub(in crate::borrow_check) fn applied_member_constraints(
+        &self, r: impl ToRegionVid
+    ) -> &[AppliedMemberConstraint] {
         let scc = self.constraint_sccs.scc(r.to_region_vid());
         binary_search_util::binary_search_slice(
             &self.member_constraints_applied,
@@ -475,6 +481,7 @@
         upvars: &[Upvar],
         mir_def_id: DefId,
         errors_buffer: &mut Vec<Diagnostic>,
+        polonius_output: Option<Rc<PoloniusOutput>>,
     ) -> Option<ClosureRegionRequirements<'tcx>> {
         self.propagate_constraints(body);
 
@@ -484,7 +491,7 @@
         // functions below, which will trigger them to report errors
         // eagerly.
         let mut outlives_requirements =
-            if infcx.tcx.is_closure(mir_def_id) { Some(vec![]) } else { None };
+            infcx.tcx.is_closure(mir_def_id).then(|| vec![]);
 
         self.check_type_tests(
             infcx,
@@ -500,16 +507,33 @@
         // multiple problems.
         let mut region_naming = RegionErrorNamingCtx::new();
 
-        self.check_universal_regions(
-            infcx,
-            body,
-            local_names,
-            upvars,
-            mir_def_id,
-            outlives_requirements.as_mut(),
-            errors_buffer,
-            &mut region_naming,
-        );
+        // In Polonius mode, the errors about missing universal region relations are in the output
+        // and need to be emitted or propagated. Otherwise, we need to check whether the
+        // constraints were too strong, and if so, emit or propagate those errors.
+        if infcx.tcx.sess.opts.debugging_opts.polonius {
+            self.check_polonius_subset_errors(
+                infcx,
+                body,
+                local_names,
+                upvars,
+                mir_def_id,
+                outlives_requirements.as_mut(),
+                errors_buffer,
+                &mut region_naming,
+                polonius_output.expect("Polonius output is unavailable despite `-Z polonius`"),
+            );
+        } else {
+            self.check_universal_regions(
+                infcx,
+                body,
+                local_names,
+                upvars,
+                mir_def_id,
+                outlives_requirements.as_mut(),
+                errors_buffer,
+                &mut region_naming,
+            );
+        }
 
         self.check_member_constraints(infcx, mir_def_id, errors_buffer);
 
@@ -700,14 +724,11 @@
         let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
             let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
             let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
-            if r1_outlives_r2 && r2_outlives_r1 {
-                Some(r1.min(r2))
-            } else if r1_outlives_r2 {
-                Some(r2)
-            } else if r2_outlives_r1 {
-                Some(r1)
-            } else {
-                None
+            match (r1_outlives_r2, r2_outlives_r1) {
+                (true, true) => Some(r1.min(r2)),
+                (true, false) => Some(r2),
+                (false, true) => Some(r1),
+                (false, false) => None,
             }
         };
         let mut min_choice = choice_regions[0];
@@ -1366,6 +1387,114 @@
         outlives_suggestion.add_suggestion(body, self, infcx, errors_buffer, region_naming);
     }
 
+    /// Checks if Polonius has found any unexpected free region relations.
+    ///
+    /// In Polonius terms, a "subset error" (or "illegal subset relation error") is the equivalent
+    /// of NLL's "checking if any region constraints were too strong": a placeholder origin `'a`
+    /// was unexpectedly found to be a subset of another placeholder origin `'b`, and means in NLL
+    /// terms that the "longer free region" `'a` outlived the "shorter free region" `'b`.
+    ///
+    /// More details can be found in this blog post by Niko:
+    /// http://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/
+    ///
+    /// In the canonical example
+    ///
+    ///     fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
+    ///
+    /// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a
+    /// constraint that `'a: 'b`. It is an error that we have no evidence that this
+    /// constraint holds.
+    ///
+    /// If `propagated_outlives_requirements` is `Some`, then we will
+    /// push unsatisfied obligations into there. Otherwise, we'll
+    /// report them as errors.
+    fn check_polonius_subset_errors(
+        &self,
+        infcx: &InferCtxt<'_, 'tcx>,
+        body: &Body<'tcx>,
+        local_names: &IndexVec<Local, Option<Symbol>>,
+        upvars: &[Upvar],
+        mir_def_id: DefId,
+        mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
+        errors_buffer: &mut Vec<Diagnostic>,
+        region_naming: &mut RegionErrorNamingCtx,
+        polonius_output: Rc<PoloniusOutput>,
+    ) {
+        debug!(
+            "check_polonius_subset_errors: {} subset_errors",
+            polonius_output.subset_errors.len()
+        );
+
+        let mut outlives_suggestion = OutlivesSuggestionBuilder::new(mir_def_id, local_names);
+
+        // Similarly to `check_universal_regions`: a free region relation, which was not explicitly
+        // declared ("known") was found by Polonius, so emit an error, or propagate the
+        // requirements for our caller into the `propagated_outlives_requirements` vector.
+        //
+        // Polonius doesn't model regions ("origins") as CFG-subsets or durations, but the
+        // `longer_fr` and `shorter_fr` terminology will still be used here, for consistency with
+        // the rest of the NLL infrastructure. The "subset origin" is the "longer free region",
+        // and the "superset origin" is the outlived "shorter free region".
+        //
+        // Note: Polonius will produce a subset error at every point where the unexpected
+        // `longer_fr`'s "placeholder loan" is contained in the `shorter_fr`. This can be helpful
+        // for diagnostics in the future, e.g. to point more precisely at the key locations
+        // requiring this constraint to hold. However, the error and diagnostics code downstream
+        // expects that these errors are not duplicated (and that they are in a certain order).
+        // Otherwise, diagnostics messages such as the ones giving names like `'1` to elided or
+        // anonymous lifetimes for example, could give these names differently, while others like
+        // the outlives suggestions or the debug output from `#[rustc_regions]` would be
+        // duplicated. The polonius subset errors are deduplicated here, while keeping the
+        // CFG-location ordering.
+        let mut subset_errors: Vec<_> = polonius_output
+            .subset_errors
+            .iter()
+            .flat_map(|(_location, subset_errors)| subset_errors.iter())
+            .collect();
+        subset_errors.sort();
+        subset_errors.dedup();
+
+        for (longer_fr, shorter_fr) in subset_errors.into_iter() {
+            debug!("check_polonius_subset_errors: subset_error longer_fr={:?},\
+                shorter_fr={:?}", longer_fr, shorter_fr);
+
+            self.report_or_propagate_universal_region_error(
+                *longer_fr,
+                *shorter_fr,
+                infcx,
+                body,
+                local_names,
+                upvars,
+                mir_def_id,
+                &mut propagated_outlives_requirements,
+                &mut outlives_suggestion,
+                errors_buffer,
+                region_naming,
+            );
+        }
+
+        // Handle the placeholder errors as usual, until the chalk-rustc-polonius triumvirate has
+        // a more complete picture on how to separate this responsibility.
+        for (fr, fr_definition) in self.definitions.iter_enumerated() {
+            match fr_definition.origin {
+                NLLRegionVariableOrigin::FreeRegion => {
+                    // handled by polonius above
+                }
+
+                NLLRegionVariableOrigin::Placeholder(placeholder) => {
+                    self.check_bound_universal_region(infcx, body, mir_def_id, fr, placeholder);
+                }
+
+                NLLRegionVariableOrigin::Existential { .. } => {
+                    // nothing to check here
+                }
+            }
+        }
+
+        // Emit outlives suggestions
+        outlives_suggestion.add_suggestion(body, self, infcx, errors_buffer, region_naming);
+    }
+
     /// Checks the final value for the free region `fr` to see if it
     /// grew too large. In particular, examine what `end(X)` points
     /// wound up in `fr`'s final value; for each `end(X)` where `X !=
@@ -1465,8 +1594,37 @@
             return None;
         }
 
+        self.report_or_propagate_universal_region_error(
+            longer_fr,
+            shorter_fr,
+            infcx,
+            body,
+            local_names,
+            upvars,
+            mir_def_id,
+            propagated_outlives_requirements,
+            outlives_suggestion,
+            errors_buffer,
+            region_naming,
+        )
+    }
+
+    fn report_or_propagate_universal_region_error(
+        &self,
+        longer_fr: RegionVid,
+        shorter_fr: RegionVid,
+        infcx: &InferCtxt<'_, 'tcx>,
+        body: &Body<'tcx>,
+        local_names: &IndexVec<Local, Option<Symbol>>,
+        upvars: &[Upvar],
+        mir_def_id: DefId,
+        propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
+        outlives_suggestion: &mut OutlivesSuggestionBuilder<'_>,
+        errors_buffer: &mut Vec<Diagnostic>,
+        region_naming: &mut RegionErrorNamingCtx,
+    ) -> Option<ErrorReported> {
         debug!(
-            "check_universal_region_relation: fr={:?} does not outlive shorter_fr={:?}",
+            "report_or_propagate_universal_region_error: fr={:?} does not outlive shorter_fr={:?}",
             longer_fr, shorter_fr,
         );
 
@@ -1475,9 +1633,9 @@
             // We'll call it `fr-` -- it's ever so slightly smaller than
             // `longer_fr`.
 
-            if let Some(fr_minus) = self.universal_region_relations.non_local_lower_bound(longer_fr)
-            {
-                debug!("check_universal_region: fr_minus={:?}", fr_minus);
+            if let Some(fr_minus) =
+                self.universal_region_relations.non_local_lower_bound(longer_fr) {
+                debug!("report_or_propagate_universal_region_error: fr_minus={:?}", fr_minus);
 
                 let blame_span_category =
                     self.find_outlives_blame_span(body, longer_fr,
@@ -1486,9 +1644,13 @@
                 // Grow `shorter_fr` until we find some non-local regions. (We
                 // always will.)  We'll call them `shorter_fr+` -- they're ever
                 // so slightly larger than `shorter_fr`.
-                let shorter_fr_plus =
-                    self.universal_region_relations.non_local_upper_bounds(&shorter_fr);
-                debug!("check_universal_region: shorter_fr_plus={:?}", shorter_fr_plus);
+                let shorter_fr_plus = self
+                    .universal_region_relations
+                    .non_local_upper_bounds(&shorter_fr);
+                debug!(
+                    "report_or_propagate_universal_region_error: shorter_fr_plus={:?}",
+                    shorter_fr_plus
+                );
                 for &&fr in &shorter_fr_plus {
                     // Push the constraint `fr-: shorter_fr+`
                     propagated_outlives_requirements.push(ClosureOutlivesRequirement {
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/region_infer/values.rs
similarity index 99%
rename from src/librustc_mir/borrow_check/nll/region_infer/values.rs
rename to src/librustc_mir/borrow_check/region_infer/values.rs
index b4414c5..0bf0cd3 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/region_infer/values.rs
@@ -1,4 +1,4 @@
-use rustc::mir::{BasicBlock, Location, Body, ReadOnlyBodyCache};
+use rustc::mir::{BasicBlock, Location, Body, ReadOnlyBodyAndCache};
 use rustc::ty::{self, RegionVid};
 use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix};
 use rustc_data_structures::fx::FxHashMap;
@@ -92,7 +92,7 @@
     /// Pushes all predecessors of `index` onto `stack`.
     crate fn push_predecessors(
         &self,
-        body: ReadOnlyBodyCache<'_, '_>,
+        body: ReadOnlyBodyAndCache<'_, '_>,
         index: PointIndex,
         stack: &mut Vec<PointIndex>,
     ) {
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/renumber.rs
similarity index 94%
rename from src/librustc_mir/borrow_check/nll/renumber.rs
rename to src/librustc_mir/borrow_check/renumber.rs
index db15d2c..ba323b1 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/renumber.rs
@@ -1,6 +1,6 @@
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::mir::{BodyCache, Location, PlaceElem, Promoted};
+use rustc::mir::{BodyAndCache, Location, PlaceElem, Promoted};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 use rustc_index::vec::IndexVec;
@@ -9,8 +9,8 @@
 /// inference variables, returning the number of variables created.
 pub fn renumber_mir<'tcx>(
     infcx: &InferCtxt<'_, 'tcx>,
-    body: &mut BodyCache<'tcx>,
-    promoted: &mut IndexVec<Promoted, BodyCache<'tcx>>,
+    body: &mut BodyAndCache<'tcx>,
+    promoted: &mut IndexVec<Promoted, BodyAndCache<'tcx>>,
 ) {
     debug!("renumber_mir()");
     debug!("renumber_mir: body.arg_count={:?}", body.arg_count);
diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/type_check/constraint_conversion.rs
similarity index 95%
rename from src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
rename to src/librustc_mir/borrow_check/type_check/constraint_conversion.rs
index 34ac96b..334477d 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
+++ b/src/librustc_mir/borrow_check/type_check/constraint_conversion.rs
@@ -1,8 +1,3 @@
-use crate::borrow_check::nll::constraints::OutlivesConstraint;
-use crate::borrow_check::nll::region_infer::TypeTest;
-use crate::borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
-use crate::borrow_check::nll::universal_regions::UniversalRegions;
-use crate::borrow_check::nll::ToRegionVid;
 use rustc::infer::canonical::QueryRegionConstraints;
 use rustc::infer::canonical::QueryOutlivesConstraint;
 use rustc::infer::outlives::env::RegionBoundPairs;
@@ -14,6 +9,14 @@
 use rustc::ty::{self, TyCtxt};
 use syntax_pos::DUMMY_SP;
 
+use crate::borrow_check::{
+    constraints::OutlivesConstraint,
+    region_infer::TypeTest,
+    type_check::{Locations, MirTypeckRegionConstraints},
+    universal_regions::UniversalRegions,
+    nll::ToRegionVid,
+};
+
 crate struct ConstraintConversion<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
     tcx: TyCtxt<'tcx>,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
rename to src/librustc_mir/borrow_check/type_check/free_region_relations.rs
index d18a8e8..03a7f97 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
@@ -1,7 +1,3 @@
-use crate::borrow_check::nll::type_check::constraint_conversion;
-use crate::borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
-use crate::borrow_check::nll::universal_regions::UniversalRegions;
-use crate::borrow_check::nll::ToRegionVid;
 use rustc::infer::canonical::QueryRegionConstraints;
 use rustc::infer::outlives::free_region_map::FreeRegionRelations;
 use rustc::infer::region_constraints::GenericKind;
@@ -14,6 +10,13 @@
 use std::rc::Rc;
 use syntax_pos::DUMMY_SP;
 
+use crate::borrow_check::{
+    type_check::constraint_conversion,
+    type_check::{Locations, MirTypeckRegionConstraints},
+    universal_regions::UniversalRegions,
+    nll::ToRegionVid,
+};
+
 #[derive(Debug)]
 crate struct UniversalRegionRelations<'tcx> {
     universal_regions: Rc<UniversalRegions<'tcx>>,
@@ -217,6 +220,11 @@
     crate fn regions_outlived_by(&self, fr1: RegionVid) -> Vec<&RegionVid> {
         self.outlives.reachable_from(&fr1)
     }
+
+    /// Returns the _non-transitive_ set of known `outlives` constraints between free regions.
+    crate fn known_outlives(&self) -> impl Iterator<Item=(&RegionVid, &RegionVid)> {
+        self.outlives.base_edges()
+    }
 }
 
 struct UniversalRegionRelationsBuilder<'this, 'tcx> {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/type_check/input_output.rs
similarity index 98%
rename from src/librustc_mir/borrow_check/nll/type_check/input_output.rs
rename to src/librustc_mir/borrow_check/type_check/input_output.rs
index 35fb677..3df0490 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/type_check/input_output.rs
@@ -7,7 +7,6 @@
 //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
 //! contain revealed `impl Trait` values).
 
-use crate::borrow_check::nll::universal_regions::UniversalRegions;
 use rustc::infer::LateBoundRegionConversionTime;
 use rustc::mir::*;
 use rustc::ty::Ty;
@@ -15,6 +14,8 @@
 use rustc_index::vec::Idx;
 use syntax_pos::Span;
 
+use crate::borrow_check::universal_regions::UniversalRegions;
+
 use super::{Locations, TypeChecker};
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/type_check/liveness/local_use_map.rs
similarity index 96%
rename from src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
rename to src/librustc_mir/borrow_check/type_check/liveness/local_use_map.rs
index d6aa314..75e4f61 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
+++ b/src/librustc_mir/borrow_check/type_check/liveness/local_use_map.rs
@@ -1,10 +1,12 @@
-use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
-use crate::util::liveness::{categorize, DefUse};
 use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{Local, Location, ReadOnlyBodyCache};
+use rustc::mir::{Local, Location, ReadOnlyBodyAndCache};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_data_structures::vec_linked_list as vll;
 
+use crate::util::liveness::{categorize, DefUse};
+
+use crate::borrow_check::region_infer::values::{PointIndex, RegionValueElements};
+
 /// A map that cross references each local with the locations where it
 /// is defined (assigned), used, or dropped. Used during liveness
 /// computation.
@@ -60,7 +62,7 @@
     crate fn build(
         live_locals: &Vec<Local>,
         elements: &RegionValueElements,
-        body: ReadOnlyBodyCache<'_, '_>,
+        body: ReadOnlyBodyAndCache<'_, '_>,
     ) -> Self {
         let nones = IndexVec::from_elem_n(None, body.local_decls.len());
         let mut local_use_map = LocalUseMap {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/type_check/liveness/mod.rs
similarity index 91%
rename from src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
rename to src/librustc_mir/borrow_check/type_check/liveness/mod.rs
index dfd505f..ee3d89e 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/liveness/mod.rs
@@ -1,17 +1,21 @@
-use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::nll::constraints::OutlivesConstraintSet;
-use crate::borrow_check::nll::facts::{AllFacts, AllFactsExt};
-use crate::borrow_check::nll::region_infer::values::RegionValueElements;
-use crate::borrow_check::nll::universal_regions::UniversalRegions;
-use crate::borrow_check::nll::ToRegionVid;
-use crate::dataflow::move_paths::MoveData;
-use crate::dataflow::FlowAtLocation;
-use crate::dataflow::MaybeInitializedPlaces;
-use rustc::mir::{Body, Local, ReadOnlyBodyCache};
+use rustc::mir::{Body, Local, ReadOnlyBodyAndCache};
 use rustc::ty::{RegionVid, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use std::rc::Rc;
 
+use crate::dataflow::move_paths::MoveData;
+use crate::dataflow::FlowAtLocation;
+use crate::dataflow::MaybeInitializedPlaces;
+
+use crate::borrow_check::{
+    location::LocationTable,
+    constraints::OutlivesConstraintSet,
+    facts::{AllFacts, AllFactsExt},
+    region_infer::values::RegionValueElements,
+    universal_regions::UniversalRegions,
+    nll::ToRegionVid,
+};
+
 use super::TypeChecker;
 
 mod local_use_map;
@@ -28,7 +32,7 @@
 /// performed before
 pub(super) fn generate<'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
     elements: &Rc<RegionValueElements>,
     flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
     move_data: &MoveData<'tcx>,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs
similarity index 68%
rename from src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
rename to src/librustc_mir/borrow_check/type_check/liveness/polonius.rs
index e67de6c..0354b0d 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
+++ b/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs
@@ -3,22 +3,21 @@
 use crate::dataflow::move_paths::{LookupResult, MoveData};
 use crate::util::liveness::{categorize, DefUse};
 use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
-use rustc::mir::{Local, Location, Place, ReadOnlyBodyCache};
+use rustc::mir::{Local, Location, Place, ReadOnlyBodyAndCache};
 use rustc::ty::subst::GenericArg;
-use rustc::ty::Ty;
 
 use super::TypeChecker;
 
-type VarPointRelations = Vec<(Local, LocationIndex)>;
-type MovePathPointRelations = Vec<(MovePathIndex, LocationIndex)>;
+type VarPointRelation = Vec<(Local, LocationIndex)>;
+type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
 
 struct UseFactsExtractor<'me> {
-    var_defined: &'me mut VarPointRelations,
-    var_used: &'me mut VarPointRelations,
+    var_defined: &'me mut VarPointRelation,
+    var_used: &'me mut VarPointRelation,
     location_table: &'me LocationTable,
     var_drop_used: &'me mut Vec<(Local, Location)>,
     move_data: &'me MoveData<'me>,
-    path_accessed_at: &'me mut MovePathPointRelations,
+    path_accessed_at: &'me mut PathPointRelation,
 }
 
 // A Visitor to walk through the MIR and extract point-wise facts
@@ -28,22 +27,22 @@
     }
 
     fn insert_def(&mut self, local: Local, location: Location) {
-        debug!("LivenessFactsExtractor::insert_def()");
+        debug!("UseFactsExtractor::insert_def()");
         self.var_defined.push((local, self.location_to_index(location)));
     }
 
     fn insert_use(&mut self, local: Local, location: Location) {
-        debug!("LivenessFactsExtractor::insert_use()");
+        debug!("UseFactsExtractor::insert_use()");
         self.var_used.push((local, self.location_to_index(location)));
     }
 
     fn insert_drop_use(&mut self, local: Local, location: Location) {
-        debug!("LivenessFactsExtractor::insert_drop_use()");
+        debug!("UseFactsExtractor::insert_drop_use()");
         self.var_drop_used.push((local, location));
     }
 
     fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
-        debug!("LivenessFactsExtractor::insert_path_access({:?}, {:?})", path, location);
+        debug!("UseFactsExtractor::insert_path_access({:?}, {:?})", path, location);
         self.path_accessed_at.push((path, self.location_to_index(location)));
     }
 
@@ -84,44 +83,39 @@
     }
 }
 
-fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty<'tcx>) {
-    debug!("add_regions(local={:?}, type={:?})", local, ty);
-    typeck.tcx().for_each_free_region(&ty, |region| {
-        let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(region);
-        debug!("add_regions for region {:?}", region_vid);
-        if let Some(facts) = typeck.borrowck_context.all_facts {
-            facts.var_uses_region.push((local, region_vid));
-        }
-    });
-}
-
 pub(super) fn populate_access_facts(
     typeck: &mut TypeChecker<'_, 'tcx>,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
     location_table: &LocationTable,
     move_data: &MoveData<'_>,
     drop_used: &mut Vec<(Local, Location)>,
 ) {
-    debug!("populate_var_liveness_facts()");
+    debug!("populate_access_facts()");
 
     if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
-        UseFactsExtractor {
+        let mut extractor = UseFactsExtractor {
             var_defined: &mut facts.var_defined,
             var_used: &mut facts.var_used,
             var_drop_used: drop_used,
             path_accessed_at: &mut facts.path_accessed_at,
             location_table,
             move_data,
-        }
-        .visit_body(body);
+        };
+        extractor.visit_body(body);
 
         facts.var_drop_used.extend(drop_used.iter().map(|&(local, location)| {
             (local, location_table.mid_index(location))
         }));
-    }
 
-    for (local, local_decl) in body.local_decls.iter_enumerated() {
-        add_var_uses_regions(typeck, local, local_decl.ty);
+        for (local, local_decl) in body.local_decls.iter_enumerated() {
+            debug!("add var_uses_regions facts - local={:?}, type={:?}", local, local_decl.ty);
+            let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
+            let universal_regions = &typeck.borrowck_context.universal_regions;
+            typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
+                let region_vid = universal_regions.to_region_vid(region);
+                facts.var_uses_region.push((local, region_vid));
+            });
+        }
     }
 }
 
@@ -133,12 +127,12 @@
     kind: &GenericArg<'tcx>,
 ) {
     debug!("add_var_drops_region(local={:?}, kind={:?}", local, kind);
-    let tcx = typeck.tcx();
-
-    tcx.for_each_free_region(kind, |drop_live_region| {
-        let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(drop_live_region);
-        if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
+    if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
+        let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
+        let universal_regions = &typeck.borrowck_context.universal_regions;
+        typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
+            let region_vid = universal_regions.to_region_vid(drop_live_region);
             facts.var_drops_region.push((local, region_vid));
-        };
-    });
+        });
+    }
 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
rename to src/librustc_mir/borrow_check/type_check/liveness/trace.rs
index 229cbed..9afd25a 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
+++ b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs
@@ -1,13 +1,5 @@
-use crate::borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
-use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
-use crate::borrow_check::nll::type_check::liveness::polonius;
-use crate::borrow_check::nll::type_check::NormalizeLocation;
-use crate::borrow_check::nll::type_check::TypeChecker;
-use crate::dataflow::indexes::MovePathIndex;
-use crate::dataflow::move_paths::MoveData;
-use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
 use rustc::infer::canonical::QueryRegionConstraints;
-use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, ReadOnlyBodyCache};
+use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, ReadOnlyBodyAndCache};
 use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
 use rustc::traits::query::type_op::outlives::DropckOutlives;
 use rustc::traits::query::type_op::TypeOp;
@@ -16,6 +8,18 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use std::rc::Rc;
 
+use crate::dataflow::indexes::MovePathIndex;
+use crate::dataflow::move_paths::MoveData;
+use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
+
+use crate::borrow_check::{
+    region_infer::values::{self, PointIndex, RegionValueElements},
+    type_check::liveness::local_use_map::LocalUseMap,
+    type_check::liveness::polonius,
+    type_check::NormalizeLocation,
+    type_check::TypeChecker,
+};
+
 /// This is the heart of the liveness computation. For each variable X
 /// that requires a liveness computation, it walks over all the uses
 /// of X and does a reverse depth-first search ("trace") through the
@@ -32,7 +36,7 @@
 /// this respects `#[may_dangle]` annotations).
 pub(super) fn trace(
     typeck: &mut TypeChecker<'_, 'tcx>,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
     elements: &Rc<RegionValueElements>,
     flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
     move_data: &MoveData<'tcx>,
@@ -71,7 +75,7 @@
     elements: &'me RegionValueElements,
 
     /// MIR we are analyzing.
-    body: ReadOnlyBodyCache<'me, 'tcx>,
+    body: ReadOnlyBodyAndCache<'me, 'tcx>,
 
     /// Mapping to/from the various indices used for initialization tracking.
     move_data: &'me MoveData<'tcx>,
@@ -249,7 +253,7 @@
         // Reverse DFS. But for drops, we do it a bit differently.
         // The stack only ever stores *terminators of blocks*. Within
         // a block, we walk back the statements in an inner loop.
-        'next_block: while let Some(term_point) = self.stack.pop() {
+        while let Some(term_point) = self.stack.pop() {
             self.compute_drop_live_points_for_block(mpi, term_point);
         }
     }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/nll/type_check/mod.rs
rename to src/librustc_mir/borrow_check/type_check/mod.rs
index de30420..663536b 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -34,30 +34,32 @@
 use rustc_index::vec::{Idx, IndexVec};
 use syntax_pos::{DUMMY_SP, Span};
 
-use crate::borrow_check::borrow_set::BorrowSet;
-use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::nll::constraints::{OutlivesConstraint, OutlivesConstraintSet};
-use crate::borrow_check::nll::facts::AllFacts;
-use crate::borrow_check::nll::member_constraints::MemberConstraintSet;
-use crate::borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
-use crate::borrow_check::nll::region_infer::values::LivenessValues;
-use crate::borrow_check::nll::region_infer::values::PlaceholderIndex;
-use crate::borrow_check::nll::region_infer::values::PlaceholderIndices;
-use crate::borrow_check::nll::region_infer::values::RegionValueElements;
-use crate::borrow_check::nll::renumber;
-use crate::borrow_check::nll::ToRegionVid;
-use crate::borrow_check::nll::type_check::free_region_relations::{
-    CreateResult, UniversalRegionRelations,
-};
-use crate::borrow_check::nll::universal_regions::{DefiningTy, UniversalRegions};
 use crate::dataflow::FlowAtLocation;
 use crate::dataflow::MaybeInitializedPlaces;
 use crate::dataflow::move_paths::MoveData;
 use crate::transform::promote_consts::should_suggest_const_in_array_repeat_expressions_attribute;
 
+use crate::borrow_check::{
+    borrow_set::BorrowSet,
+    location::LocationTable,
+    constraints::{OutlivesConstraintSet, OutlivesConstraint},
+    member_constraints::MemberConstraintSet,
+    facts::AllFacts,
+    region_infer::values::{
+        LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
+    },
+    region_infer::{ClosureRegionRequirementsExt, TypeTest},
+    type_check::free_region_relations::{
+        CreateResult, UniversalRegionRelations,
+    },
+    universal_regions::{DefiningTy, UniversalRegions},
+    nll::ToRegionVid,
+    renumber,
+};
+
 macro_rules! span_mirbug {
     ($context:expr, $elem:expr, $($message:tt)*) => ({
-        $crate::borrow_check::nll::type_check::mirbug(
+        $crate::borrow_check::type_check::mirbug(
             $context.tcx(),
             $context.last_span,
             &format!(
@@ -117,8 +119,8 @@
 pub(crate) fn type_check<'tcx>(
     infcx: &InferCtxt<'_, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
-    promoted: &IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
+    promoted: &IndexVec<Promoted, ReadOnlyBodyAndCache<'_, 'tcx>>,
     mir_def_id: DefId,
     universal_regions: &Rc<UniversalRegions<'tcx>>,
     location_table: &LocationTable,
@@ -182,7 +184,7 @@
                 move_data,
                 location_table);
 
-            translate_outlives_facts(cx.borrowck_context);
+            translate_outlives_facts(&mut cx);
         },
     );
 
@@ -196,8 +198,8 @@
     infcx: &'a InferCtxt<'a, 'tcx>,
     mir_def_id: DefId,
     param_env: ty::ParamEnv<'tcx>,
-    body: ReadOnlyBodyCache<'a, 'tcx>,
-    promoted: &'a IndexVec<Promoted, ReadOnlyBodyCache<'_, 'tcx>>,
+    body: ReadOnlyBodyAndCache<'a, 'tcx>,
+    promoted: &'a IndexVec<Promoted, ReadOnlyBodyAndCache<'_, 'tcx>>,
     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
     implicit_region_bound: ty::Region<'tcx>,
     borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
@@ -206,7 +208,7 @@
 ) -> R {
     let mut checker = TypeChecker::new(
         infcx,
-        body.body(),
+        *body,
         mir_def_id,
         param_env,
         region_bound_pairs,
@@ -215,7 +217,7 @@
         universal_region_relations,
     );
     let errors_reported = {
-        let mut verifier = TypeVerifier::new(&mut checker, body.body(), promoted);
+        let mut verifier = TypeVerifier::new(&mut checker, *body, promoted);
         verifier.visit_body(body);
         verifier.errors_reported
     };
@@ -228,8 +230,10 @@
     extra(&mut checker)
 }
 
-fn translate_outlives_facts(cx: &mut BorrowCheckContext<'_, '_>) {
+fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
+    let cx = &mut typeck.borrowck_context;
     if let Some(facts) = cx.all_facts {
+        let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
         let location_table = cx.location_table;
         facts
             .outlives
@@ -272,7 +276,7 @@
 struct TypeVerifier<'a, 'b, 'tcx> {
     cx: &'a mut TypeChecker<'b, 'tcx>,
     body: &'b Body<'tcx>,
-    promoted: &'b IndexVec<Promoted, ReadOnlyBodyCache<'b, 'tcx>>,
+    promoted: &'b IndexVec<Promoted, ReadOnlyBodyAndCache<'b, 'tcx>>,
     last_span: Span,
     mir_def_id: DefId,
     errors_reported: bool,
@@ -396,7 +400,7 @@
         }
     }
 
-    fn visit_body(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>) {
+    fn visit_body(&mut self, body: ReadOnlyBodyAndCache<'_, 'tcx>) {
         self.sanitize_type(&"return type", body.return_ty());
         for local_decl in &body.local_decls {
             self.sanitize_type(local_decl, local_decl.ty);
@@ -412,7 +416,7 @@
     fn new(
         cx: &'a mut TypeChecker<'b, 'tcx>,
         body: &'b Body<'tcx>,
-        promoted: &'b IndexVec<Promoted, ReadOnlyBodyCache<'b, 'tcx>>,
+        promoted: &'b IndexVec<Promoted, ReadOnlyBodyAndCache<'b, 'tcx>>,
     ) -> Self {
         TypeVerifier {
             body,
@@ -548,14 +552,14 @@
 
     fn sanitize_promoted(
         &mut self,
-        promoted_body: ReadOnlyBodyCache<'b, 'tcx>,
+        promoted_body: ReadOnlyBodyAndCache<'b, 'tcx>,
         location: Location
     ) {
         // Determine the constraints from the promoted MIR by running the type
         // checker on the promoted MIR, then transfer the constraints back to
         // the main MIR, changing the locations to the provided location.
 
-        let parent_body = mem::replace(&mut self.body, promoted_body.body());
+        let parent_body = mem::replace(&mut self.body, *promoted_body);
 
         // Use new sets of constraints and closure bounds so that we can
         // modify their locations.
@@ -673,23 +677,16 @@
                     }),
                 )
             }
-            ProjectionElem::Subslice { from, to } => PlaceTy::from_ty(
+            ProjectionElem::Subslice { from, to, from_end } => PlaceTy::from_ty(
                 match base_ty.kind {
-                    ty::Array(inner, size) => {
-                        let size = size.eval_usize(tcx, self.cx.param_env);
-                        let min_size = (from as u64) + (to as u64);
-                        if let Some(rest_size) = size.checked_sub(min_size) {
-                            tcx.mk_array(inner, rest_size)
-                        } else {
-                            span_mirbug_and_err!(
-                                self,
-                                place,
-                                "taking too-small slice of {:?}",
-                                base_ty
-                            )
-                        }
+                    ty::Array(inner, _) => {
+                        assert!(!from_end, "array subslices should not use from_end");
+                        tcx.mk_array(inner, (to - from) as u64)
                     }
-                    ty::Slice(..) => base_ty,
+                    ty::Slice(..) => {
+                        assert!(from_end, "slice subslices should use from_end");
+                        base_ty
+                    },
                     _ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty),
                 },
             ),
@@ -1378,7 +1375,7 @@
 
     fn check_stmt(
         &mut self,
-        body: ReadOnlyBodyCache<'_, 'tcx>,
+        body: ReadOnlyBodyAndCache<'_, 'tcx>,
         stmt: &Statement<'tcx>,
         location: Location)
     {
@@ -1994,7 +1991,7 @@
 
     fn check_rvalue(
         &mut self,
-        body: ReadOnlyBodyCache<'_, 'tcx>,
+        body: ReadOnlyBodyAndCache<'_, 'tcx>,
         rvalue: &Rvalue<'tcx>,
         location: Location)
     {
@@ -2489,6 +2486,7 @@
         // that occurs when we are borrowing an unsafe place, for
         // example).
         if let Some(all_facts) = all_facts {
+            let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
             if let Some(borrow_index) = borrow_set.location_map.get(&location) {
                 let region_vid = borrow_region.to_region_vid();
                 all_facts.borrow_region.push((
@@ -2766,7 +2764,7 @@
         })
     }
 
-    fn typeck_mir(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>) {
+    fn typeck_mir(&mut self, body: ReadOnlyBodyAndCache<'_, 'tcx>) {
         self.last_span = body.span;
         debug!("run_on_mir: {:?}", body.span);
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs
similarity index 96%
rename from src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
rename to src/librustc_mir/borrow_check/type_check/relate_tys.rs
index 80bf047..80da8a8 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
+++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs
@@ -1,5 +1,3 @@
-use crate::borrow_check::nll::constraints::OutlivesConstraint;
-use crate::borrow_check::nll::type_check::{BorrowCheckContext, Locations};
 use rustc::infer::nll_relate::{TypeRelating, TypeRelatingDelegate, NormalizationStrategy};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 use rustc::mir::ConstraintCategory;
@@ -8,6 +6,9 @@
 use rustc::ty::relate::TypeRelation;
 use rustc::ty::{self, Ty};
 
+use crate::borrow_check::constraints::OutlivesConstraint;
+use crate::borrow_check::type_check::{BorrowCheckContext, Locations};
+
 /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
 ///
 /// - "Covariant" `a <: b`
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs
similarity index 97%
rename from src/librustc_mir/borrow_check/nll/universal_regions.rs
rename to src/librustc_mir/borrow_check/universal_regions.rs
index fbedac4..c035303 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/universal_regions.rs
@@ -25,7 +25,7 @@
 use rustc_errors::DiagnosticBuilder;
 use std::iter;
 
-use super::ToRegionVid;
+use crate::borrow_check::nll::ToRegionVid;
 
 #[derive(Debug)]
 pub struct UniversalRegions<'tcx> {
@@ -312,9 +312,9 @@
         match self.defining_ty {
             DefiningTy::Closure(def_id, substs) => {
                 err.note(&format!(
-                    "defining type: {:?} with closure substs {:#?}",
-                    def_id,
-                    &substs[..]
+                    "defining type: {} with closure substs {:#?}",
+                    tcx.def_path_str_with_substs(def_id, substs),
+                    &substs[tcx.generics_of(def_id).parent_count..],
                 ));
 
                 // FIXME: It'd be nice to print the late-bound regions
@@ -332,9 +332,9 @@
             }
             DefiningTy::Generator(def_id, substs, _) => {
                 err.note(&format!(
-                    "defining type: {:?} with generator substs {:#?}",
-                    def_id,
-                    &substs[..]
+                    "defining type: {} with generator substs {:#?}",
+                    tcx.def_path_str_with_substs(def_id, substs),
+                    &substs[tcx.generics_of(def_id).parent_count..],
                 ));
 
                 // FIXME: As above, we'd like to print out the region
@@ -350,16 +350,14 @@
             }
             DefiningTy::FnDef(def_id, substs) => {
                 err.note(&format!(
-                    "defining type: {:?} with substs {:#?}",
-                    def_id,
-                    &substs[..]
+                    "defining type: {}",
+                    tcx.def_path_str_with_substs(def_id, substs),
                 ));
             }
             DefiningTy::Const(def_id, substs) => {
                 err.note(&format!(
-                    "defining constant type: {:?} with substs {:#?}",
-                    def_id,
-                    &substs[..]
+                    "defining constant type: {}",
+                    tcx.def_path_str_with_substs(def_id, substs),
                 ));
             }
         }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index f5dc09c..07a44b1 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -65,7 +65,14 @@
                     _ => false,
                 };
 
-                unpack!(block = this.as_local_rvalue(block, source));
+                // (#66975) Source could be a const of type `!`, so has to
+                // exist in the generated MIR.
+                unpack!(block = this.as_temp(
+                    block,
+                    this.local_scope(),
+                    source,
+                    Mutability::Mut,
+                ));
 
                 // This is an optimization. If the expression was a call then we already have an
                 // unreachable block. Don't bother to terminate it and create a new one.
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index c893d6f..e320811 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -680,7 +680,7 @@
                     }
                 })();
 
-                if no_overlap == Some(true) {
+                if let Some(true) = no_overlap {
                     // Testing range does not overlap with pattern range,
                     // so the pattern can be matched only if this test fails.
                     Some(1)
@@ -690,7 +690,7 @@
             }
 
             (&TestKind::Range(range), &PatKind::Constant { value }) => {
-                if self.const_range_contains(range, value) == Some(false) {
+                if let Some(false) = self.const_range_contains(range, value) {
                     // `value` is not contained in the testing range,
                     // so `value` can be matched only if this test fails.
                     Some(1)
diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs
index aec9e6e..ec8b3c5 100644
--- a/src/librustc_mir/build/matches/util.rs
+++ b/src/librustc_mir/build/matches/util.rs
@@ -2,6 +2,7 @@
 use crate::build::matches::MatchPair;
 use crate::hair::*;
 use rustc::mir::*;
+use rustc::ty;
 use smallvec::SmallVec;
 use std::u32;
 use std::convert::TryInto;
@@ -31,9 +32,17 @@
                                      prefix: &'pat [Pat<'tcx>],
                                      opt_slice: Option<&'pat Pat<'tcx>>,
                                      suffix: &'pat [Pat<'tcx>]) {
-        let min_length = prefix.len() + suffix.len();
-        let min_length = min_length.try_into().unwrap();
         let tcx = self.hir.tcx();
+        let (min_length, exact_size) = match place.ty(&self.local_decls, tcx).ty.kind {
+            ty::Array(_, length) => (
+                length.eval_usize(tcx, self.hir.param_env).try_into().unwrap(),
+                true
+            ),
+            _ => (
+                (prefix.len() + suffix.len()).try_into().unwrap(),
+                false,
+            ),
+        };
 
         match_pairs.extend(
             prefix.iter()
@@ -50,10 +59,15 @@
         );
 
         if let Some(subslice_pat) = opt_slice {
-            let subslice = tcx.mk_place_elem(place.clone(),ProjectionElem::Subslice {
-                from: prefix.len() as u32,
-                to: suffix.len() as u32
-            });
+            let suffix_len = suffix.len() as u32;
+            let subslice = tcx.mk_place_elem(
+                place.clone(),
+                ProjectionElem::Subslice {
+                    from: prefix.len() as u32,
+                    to: if exact_size { min_length - suffix_len } else { suffix_len },
+                    from_end: !exact_size,
+                },
+            );
             match_pairs.push(MatchPair::new(subslice, subslice_pat));
         }
 
@@ -62,10 +76,11 @@
                   .rev()
                   .enumerate()
                   .map(|(idx, subpattern)| {
+                      let end_offset = (idx + 1) as u32;
                       let elem = ProjectionElem::ConstantIndex {
-                          offset: (idx+1) as u32,
+                          offset: if exact_size { min_length - end_offset } else { end_offset },
                           min_length,
-                          from_end: true,
+                          from_end: !exact_size,
                       };
                       let place = tcx.mk_place_elem(place.clone(), elem);
                       MatchPair::new(place, subpattern)
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index b84461d..0009eb4 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -24,7 +24,7 @@
 use super::lints;
 
 /// Construct the MIR for a given `DefId`.
-pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyCache<'_> {
+pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     // Figure out what primary body this item has.
@@ -196,7 +196,7 @@
 
         lints::check(tcx, &body, def_id);
 
-        let mut body = BodyCache::new(body);
+        let mut body = BodyAndCache::new(body);
         body.ensure_predecessors();
         body
     })
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 968a8a7..b219fec 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -9,11 +9,10 @@
 
 use rustc::hir::def::DefKind;
 use rustc::hir::def_id::DefId;
-use rustc::middle::lang_items::PanicLocationLangItem;
 use rustc::mir::interpret::{ConstEvalErr, ErrorHandled, ScalarMaybeUndef};
 use rustc::mir;
 use rustc::ty::{self, Ty, TyCtxt, subst::Subst};
-use rustc::ty::layout::{self, LayoutOf, VariantIdx};
+use rustc::ty::layout::{self, HasTyCtxt, LayoutOf, VariantIdx};
 use rustc::traits::Reveal;
 use rustc_data_structures::fx::FxHashMap;
 use crate::interpret::eval_nullary_intrinsic;
@@ -348,7 +347,11 @@
                 //
                 // For the moment we only do this for functions which take no arguments
                 // (or all arguments are ZSTs) so that we don't memoize too much.
-                if args.iter().all(|a| a.layout.is_zst()) {
+                //
+                // Because `#[track_caller]` adds an implicit non-ZST argument, we also cannot
+                // perform this optimization on items tagged with it.
+                let no_implicit_args = !instance.def.requires_caller_location(ecx.tcx());
+                if args.iter().all(|a| a.layout.is_zst()) && no_implicit_args {
                     let gid = GlobalId { instance, promoted: None };
                     ecx.eval_const_fn_call(gid, ret)?;
                     return Ok(None);
@@ -366,7 +369,7 @@
         }
         // This is a const fn. Call it.
         Ok(Some(match ecx.load_mir(instance.def, None) {
-            Ok(body) => body.body(),
+            Ok(body) => *body,
             Err(err) => {
                 if let err_unsup!(NoMirFor(ref path)) = err.kind {
                     return Err(
@@ -559,11 +562,7 @@
     trace!("const_caller_location: {}:{}:{}", file, line, col);
     let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all());
 
-    let loc_ty = tcx.mk_imm_ref(
-        tcx.lifetimes.re_static,
-        tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None))
-            .subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())),
-    );
+    let loc_ty = tcx.caller_location_ty();
     let loc_place = ecx.alloc_caller_location(file, line, col);
     intern_const_alloc_recursive(&mut ecx, None, loc_place).unwrap();
     let loc_const = ty::Const {
@@ -743,7 +742,7 @@
 
     let res = ecx.load_mir(cid.instance.def, cid.promoted);
     res.and_then(
-        |body| eval_body_using_ecx(&mut ecx, cid, body.body())
+        |body| eval_body_using_ecx(&mut ecx, cid, *body)
     ).and_then(|place| {
         Ok(RawConst {
             alloc_id: place.ptr.assert_ptr().alloc_id,
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 7e7652c..5433b7f 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -1,6 +1,3 @@
-use crate::borrow_check::borrow_set::{BorrowSet, BorrowData};
-use crate::borrow_check::place_ext::PlaceExt;
-
 use rustc::mir::{self, Location, Place, PlaceBase, Body};
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::RegionVid;
@@ -9,10 +6,11 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::vec::{Idx, IndexVec};
 
+use crate::borrow_check::{
+    ToRegionVid, BorrowSet, BorrowData, RegionInferenceContext, PlaceExt, PlaceConflictBias,
+    places_conflict,
+};
 use crate::dataflow::{BitDenotation, BottomValue, GenKillSet};
-use crate::borrow_check::nll::region_infer::RegionInferenceContext;
-use crate::borrow_check::nll::ToRegionVid;
-use crate::borrow_check::places_conflict;
 
 use std::rc::Rc;
 
@@ -221,13 +219,13 @@
             // locations.
             let definitely_conflicting_borrows = other_borrows_of_local
                 .filter(|&&i| {
-                    places_conflict::places_conflict(
+                    places_conflict(
                         self.tcx,
                         self.param_env,
                         self.body,
                         &self.borrow_set.borrows[i].borrowed_place,
                         place,
-                        places_conflict::PlaceConflictBias::NoOverlap)
+                        PlaceConflictBias::NoOverlap)
                 });
 
             trans.kill_all(definitely_conflicting_borrows);
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index c4b97d1..b8abe6d 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -75,20 +75,20 @@
 /// Dataflow analysis that determines whether each local requires storage at a
 /// given location; i.e. whether its storage can go away without being observed.
 pub struct RequiresStorage<'mir, 'tcx> {
-    body: ReadOnlyBodyCache<'mir, 'tcx>,
+    body: ReadOnlyBodyAndCache<'mir, 'tcx>,
     borrowed_locals:
         RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
 }
 
 impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
     pub fn new(
-        body: ReadOnlyBodyCache<'mir, 'tcx>,
+        body: ReadOnlyBodyAndCache<'mir, 'tcx>,
         borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>,
     ) -> Self {
         RequiresStorage {
             body,
             borrowed_locals: RefCell::new(
-                DataflowResultsCursor::new(borrowed_locals, body.body())
+                DataflowResultsCursor::new(borrowed_locals, *body)
             ),
         }
     }
diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
index d97f3b7..0665c0f 100644
--- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs
+++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
@@ -49,8 +49,8 @@
             ProjectionElem::Deref => ProjectionElem::Deref,
             ProjectionElem::Field(ref f, ty) => ProjectionElem::Field(f.clone(), ty.lift()),
             ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()),
-            ProjectionElem::Subslice { from, to } => {
-                ProjectionElem::Subslice { from: from, to: to }
+            ProjectionElem::Subslice { from, to, from_end } => {
+                ProjectionElem::Subslice { from, to, from_end }
             }
             ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
                 ProjectionElem::ConstantIndex { offset, min_length, from_end }
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 52016d4..fa0864e 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -4,7 +4,7 @@
 use rustc_index::vec::IndexVec;
 use smallvec::{smallvec, SmallVec};
 
-use std::collections::hash_map::Entry;
+use std::convert::TryInto;
 use std::mem;
 
 use super::abs_domain::Lift;
@@ -17,12 +17,13 @@
 struct MoveDataBuilder<'a, 'tcx> {
     body: &'a Body<'tcx>,
     tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     data: MoveData<'tcx>,
     errors: Vec<(Place<'tcx>, MoveError<'tcx>)>,
 }
 
 impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
-    fn new(body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
+    fn new(body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
         let mut move_paths = IndexVec::new();
         let mut path_map = IndexVec::new();
         let mut init_path_map = IndexVec::new();
@@ -30,6 +31,7 @@
         MoveDataBuilder {
             body,
             tcx,
+            param_env,
             errors: Vec::new(),
             data: MoveData {
                 moves: IndexVec::new(),
@@ -148,42 +150,47 @@
                             InteriorOfSliceOrArray { ty: place_ty, is_index: true },
                         ));
                     }
-                    _ => {
-                        // FIXME: still badly broken
-                    }
+                    _ => {}
                 },
                 _ => {}
             };
 
-            let proj = &place.projection[..i+1];
-            base = match self
-                .builder
-                .data
-                .rev_lookup
-                .projections
-                .entry((base, elem.lift()))
-                {
-                    Entry::Occupied(ent) => *ent.get(),
-                    Entry::Vacant(ent) => {
-                        let path = MoveDataBuilder::new_move_path(
-                            &mut self.builder.data.move_paths,
-                            &mut self.builder.data.path_map,
-                            &mut self.builder.data.init_path_map,
-                            Some(base),
-                            Place {
-                                base: place.base.clone(),
-                                projection: tcx.intern_place_elems(proj),
-                            },
-                        );
-                        ent.insert(path);
-                        path
-                    }
-                };
+            base = self.add_move_path(base, elem, |tcx| {
+                Place {
+                    base: place.base.clone(),
+                    projection: tcx.intern_place_elems(&place.projection[..i+1]),
+                }
+            });
         }
 
         Ok(base)
     }
 
+    fn add_move_path(
+        &mut self,
+        base: MovePathIndex,
+        elem: &PlaceElem<'tcx>,
+        mk_place: impl FnOnce(TyCtxt<'tcx>) -> Place<'tcx>,
+    ) -> MovePathIndex {
+        let MoveDataBuilder {
+            data: MoveData { rev_lookup, move_paths, path_map, init_path_map, .. },
+            tcx,
+            ..
+        } = self.builder;
+        *rev_lookup.projections
+            .entry((base, elem.lift()))
+            .or_insert_with(move || {
+                let path = MoveDataBuilder::new_move_path(
+                    move_paths,
+                    path_map,
+                    init_path_map,
+                    Some(base),
+                    mk_place(*tcx),
+                );
+                path
+            })
+    }
+
     fn create_move_path(&mut self, place: &Place<'tcx>) {
         // This is an non-moving access (such as an overwrite or
         // drop), so this not being a valid move path is OK.
@@ -214,8 +221,9 @@
 pub(super) fn gather_moves<'tcx>(
     body: &Body<'tcx>,
     tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
 ) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
-    let mut builder = MoveDataBuilder::new(body, tcx);
+    let mut builder = MoveDataBuilder::new(body, tcx, param_env);
 
     builder.gather_args();
 
@@ -411,20 +419,67 @@
     fn gather_move(&mut self, place: &Place<'tcx>) {
         debug!("gather_move({:?}, {:?})", self.loc, place);
 
-        let path = match self.move_path_for(place) {
-            Ok(path) | Err(MoveError::UnionMove { path }) => path,
-            Err(error @ MoveError::IllegalMove { .. }) => {
-                self.builder.errors.push((place.clone(), error));
-                return;
+        if let [
+            ref base @ ..,
+            ProjectionElem::Subslice { from, to, from_end: false },
+        ] = **place.projection {
+            // Split `Subslice` patterns into the corresponding list of
+            // `ConstIndex` patterns. This is done to ensure that all move paths
+            // are disjoint, which is expected by drop elaboration.
+            let base_place = Place {
+                base: place.base.clone(),
+                projection: self.builder.tcx.intern_place_elems(base),
+            };
+            let base_path = match self.move_path_for(&base_place) {
+                Ok(path) => path,
+                Err(MoveError::UnionMove { path }) => {
+                    self.record_move(place, path);
+                    return;
+                }
+                Err(error @ MoveError::IllegalMove { .. }) => {
+                    self.builder.errors.push((base_place, error));
+                    return;
+                }
+            };
+            let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
+            let len: u32 = match base_ty.kind {
+                ty::Array(_, size) => {
+                    let length = size.eval_usize(self.builder.tcx, self.builder.param_env);
+                    length.try_into().expect(
+                        "slice pattern of array with more than u32::MAX elements"
+                    )
+                }
+                _ => bug!("from_end: false slice pattern of non-array type"),
+            };
+            for offset in from..to {
+                let elem = ProjectionElem::ConstantIndex {
+                    offset,
+                    min_length: len,
+                    from_end: false,
+                };
+                let path = self.add_move_path(
+                    base_path,
+                    &elem,
+                    |tcx| tcx.mk_place_elem(base_place.clone(), elem),
+                );
+                self.record_move(place, path);
             }
-        };
-        let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc });
+        } else {
+            match self.move_path_for(place) {
+                Ok(path) | Err(MoveError::UnionMove { path }) => self.record_move(place, path),
+                Err(error @ MoveError::IllegalMove { .. }) => {
+                    self.builder.errors.push((place.clone(), error));
+                }
+            };
+        }
+    }
 
+    fn record_move(&mut self, place: &Place<'tcx>, path: MovePathIndex) {
+        let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc });
         debug!(
             "gather_move({:?}, {:?}): adding move {:?} of {:?}",
             self.loc, place, move_out, path
         );
-
         self.builder.data.path_map[path].push(move_out);
         self.builder.data.loc_map[self.loc].push(move_out);
     }
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index b599f47..89ef9b2 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -1,6 +1,6 @@
 use core::slice::Iter;
 use rustc::mir::*;
-use rustc::ty::{Ty, TyCtxt};
+use rustc::ty::{Ty, TyCtxt, ParamEnv};
 use rustc::util::nodemap::FxHashMap;
 use rustc_index::vec::{Enumerated, Idx, IndexVec};
 use smallvec::SmallVec;
@@ -318,8 +318,9 @@
     pub fn gather_moves(
         body: &Body<'tcx>,
         tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
     ) -> Result<Self, (Self, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
-        builder::gather_moves(body, tcx)
+        builder::gather_moves(body, tcx, param_env)
     }
 
     /// For the move path `mpi`, returns the root local variable (if any) that starts the path.
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 37a9381..c372032 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -238,7 +238,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::hir::{HirId, RangeEnd};
 use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx};
-use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
 
 use rustc::lint;
 use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
@@ -354,7 +354,7 @@
 }
 
 impl<'tcx> Pat<'tcx> {
-    fn is_wildcard(&self) -> bool {
+    pub(super) fn is_wildcard(&self) -> bool {
         match *self.kind {
             PatKind::Binding { subpattern: None, .. } | PatKind::Wild => true,
             _ => false,
@@ -596,9 +596,21 @@
         }
     }
 
-    fn is_local(&self, ty: Ty<'tcx>) -> bool {
+    // Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
+    pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
         match ty.kind {
-            ty::Adt(adt_def, ..) => adt_def.did.is_local(),
+            ty::Adt(def, ..) => {
+                def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
+            }
+            _ => false,
+        }
+    }
+
+    // Returns whether the given variant is from another crate and has its fields declared
+    // `#[non_exhaustive]`.
+    fn is_foreign_non_exhaustive_variant(&self, ty: Ty<'tcx>, variant: &VariantDef) -> bool {
+        match ty.kind {
+            ty::Adt(def, ..) => variant.is_field_list_non_exhaustive() && !def.did.is_local(),
             _ => false,
         }
     }
@@ -758,6 +770,10 @@
     // Returns the set of constructors covered by `self` but not by
     // anything in `other_ctors`.
     fn subtract_ctors(&self, other_ctors: &Vec<Constructor<'tcx>>) -> Vec<Constructor<'tcx>> {
+        if other_ctors.is_empty() {
+            return vec![self.clone()];
+        }
+
         match self {
             // Those constructors can only match themselves.
             Single | Variant(_) | ConstantValue(..) | FloatRange(..) => {
@@ -858,8 +874,7 @@
                         vec![Pat::wildcard_from_ty(substs.type_at(0))]
                     } else {
                         let variant = &adt.variants[self.variant_index_for_adt(cx, adt)];
-                        let is_non_exhaustive =
-                            variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
+                        let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(ty, variant);
                         variant
                             .fields
                             .iter()
@@ -1205,6 +1220,8 @@
 ///
 /// We make sure to omit constructors that are statically impossible. E.g., for
 /// `Option<!>`, we do not include `Some(_)` in the returned list of constructors.
+/// Invariant: this returns an empty `Vec` if and only if the type is uninhabited (as determined by
+/// `cx.is_uninhabited()`).
 fn all_constructors<'a, 'tcx>(
     cx: &mut MatchCheckCtxt<'a, 'tcx>,
     pcx: PatCtxt<'tcx>,
@@ -1235,47 +1252,45 @@
             vec![Slice(Slice { array_len: None, kind })]
         }
         ty::Adt(def, substs) if def.is_enum() => {
-            let ctors: Vec<_> = def
-                .variants
-                .iter()
-                .filter(|v| {
-                    !cx.tcx.features().exhaustive_patterns
-                        || !v
-                            .uninhabited_from(cx.tcx, substs, def.adt_kind())
+            let ctors: Vec<_> = if cx.tcx.features().exhaustive_patterns {
+                // If `exhaustive_patterns` is enabled, we exclude variants known to be
+                // uninhabited.
+                def.variants
+                    .iter()
+                    .filter(|v| {
+                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind())
                             .contains(cx.tcx, cx.module)
-                })
-                .map(|v| Variant(v.def_id))
-                .collect();
-
-            // If our scrutinee is *privately* an empty enum, we must treat it as though it had an
-            // "unknown" constructor (in that case, all other patterns obviously can't be variants)
-            // to avoid exposing its emptyness. See the `match_privately_empty` test for details.
-            // FIXME: currently the only way I know of something can be a privately-empty enum is
-            // when the exhaustive_patterns feature flag is not present, so this is only needed for
-            // that case.
-            let is_privately_empty = ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
-            // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
-            // additionnal "unknown" constructor.
-            let is_declared_nonexhaustive =
-                def.is_variant_list_non_exhaustive() && !cx.is_local(pcx.ty);
-
-            if is_privately_empty || is_declared_nonexhaustive {
-                // There is no point in enumerating all possible variants, because the user can't
-                // actually match against them themselves. So we return only the fictitious
-                // constructor.
-                // E.g., in an example like:
-                // ```
-                //     let err: io::ErrorKind = ...;
-                //     match err {
-                //         io::ErrorKind::NotFound => {},
-                //     }
-                // ```
-                // we don't want to show every possible IO error, but instead have only `_` as the
-                // witness.
-                vec![NonExhaustive]
+                    })
+                    .map(|v| Variant(v.def_id))
+                    .collect()
             } else {
-                ctors
-            }
+                def.variants.iter().map(|v| Variant(v.def_id)).collect()
+            };
+
+            // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
+            // additional "unknown" constructor.
+            // There is no point in enumerating all possible variants, because the user can't
+            // actually match against them all themselves. So we always return only the fictitious
+            // constructor.
+            // E.g., in an example like:
+            // ```
+            //     let err: io::ErrorKind = ...;
+            //     match err {
+            //         io::ErrorKind::NotFound => {},
+            //     }
+            // ```
+            // we don't want to show every possible IO error, but instead have only `_` as the
+            // witness.
+            let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
+
+            // If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
+            // as though it had an "unknown" constructor to avoid exposing its emptyness. Note that
+            // an empty match will still be considered exhaustive because that case is handled
+            // separately in `check_match`.
+            let is_secretly_empty =
+                def.variants.is_empty() && !cx.tcx.features().exhaustive_patterns;
+
+            if is_secretly_empty || is_declared_nonexhaustive { vec![NonExhaustive] } else { ctors }
         }
         ty::Char => {
             vec![
@@ -1605,6 +1620,7 @@
     v: &PatStack<'p, 'tcx>,
     witness_preference: WitnessPreference,
     hir_id: HirId,
+    is_top_level: bool,
 ) -> Usefulness<'tcx, 'p> {
     let &Matrix(ref rows) = matrix;
     debug!("is_useful({:#?}, {:#?})", matrix, v);
@@ -1632,7 +1648,7 @@
         let mut unreachable_pats = Vec::new();
         let mut any_is_useful = false;
         for v in vs {
-            let res = is_useful(cx, &matrix, &v, witness_preference, hir_id);
+            let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, false);
             match res {
                 Useful(pats) => {
                     any_is_useful = true;
@@ -1732,7 +1748,7 @@
         } else {
             let matrix = matrix.specialize_wildcard();
             let v = v.to_tail();
-            let usefulness = is_useful(cx, &matrix, &v, witness_preference, hir_id);
+            let usefulness = is_useful(cx, &matrix, &v, witness_preference, hir_id, false);
 
             // In this case, there's at least one "free"
             // constructor that is only matched against by
@@ -1761,7 +1777,10 @@
             // `(<direction-1>, <direction-2>, true)` - we are
             // satisfied with `(_, _, true)`. In this case,
             // `used_ctors` is empty.
-            if missing_ctors.all_ctors_are_missing() {
+            // The exception is: if we are at the top-level, for example in an empty match, we
+            // sometimes prefer reporting the list of constructors instead of just `_`.
+            let report_ctors_rather_than_wildcard = is_top_level && !IntRange::is_integral(pcx.ty);
+            if missing_ctors.all_ctors_are_missing() && !report_ctors_rather_than_wildcard {
                 // All constructors are unused. Add a wild pattern
                 // rather than each individual constructor.
                 usefulness.apply_wildcard(pcx.ty)
@@ -1793,7 +1812,7 @@
         cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty));
     let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns);
     v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns)
-        .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id))
+        .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, false))
         .map(|u| u.apply_constructor(cx, &ctor, lty))
         .unwrap_or(NotUseful)
 }
@@ -2308,7 +2327,7 @@
 
         PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
             let ref variant = adt_def.variants[variant_index];
-            let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(pat.ty);
+            let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant);
             Some(Variant(variant.def_id))
                 .filter(|variant_constructor| variant_constructor == constructor)
                 .map(|_| {
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 737af3e..8156cfe 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -148,8 +148,8 @@
                         self.tables,
                     );
                     patcx.include_lint_checks();
-                    let pattern: &_ =
-                        cx.pattern_arena.alloc(expand_pattern(cx, patcx.lower_pattern(&arm.pat)));
+                    let pattern = patcx.lower_pattern(&arm.pat);
+                    let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
                     if !patcx.errors.is_empty() {
                         patcx.report_inlining_errors(arm.pat.span);
                         have_errors = true;
@@ -166,73 +166,12 @@
             // Fourth, check for unreachable arms.
             let matrix = check_arms(cx, &inlined_arms, source);
 
-            // Then, if the match has no arms, check whether the scrutinee
-            // is uninhabited.
-            let pat_ty = self.tables.node_type(scrut.hir_id);
-            let module = self.tcx.hir().get_module_parent(scrut.hir_id);
-            let mut def_span = None;
-            let mut missing_variants = vec![];
-            if inlined_arms.is_empty() {
-                let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns {
-                    self.tcx.is_ty_uninhabited_from(module, pat_ty)
-                } else {
-                    match pat_ty.kind {
-                        ty::Never => true,
-                        ty::Adt(def, _) => {
-                            def_span = self.tcx.hir().span_if_local(def.did);
-                            if def.variants.len() < 4 && !def.variants.is_empty() {
-                                // keep around to point at the definition of non-covered variants
-                                missing_variants =
-                                    def.variants.iter().map(|variant| variant.ident).collect();
-                            }
-
-                            let is_non_exhaustive_and_non_local =
-                                def.is_variant_list_non_exhaustive() && !def.did.is_local();
-
-                            !(is_non_exhaustive_and_non_local) && def.variants.is_empty()
-                        }
-                        _ => false,
-                    }
-                };
-                if !scrutinee_is_uninhabited {
-                    // We know the type is inhabited, so this must be wrong
-                    let mut err = create_e0004(
-                        self.tcx.sess,
-                        scrut.span,
-                        format!(
-                            "non-exhaustive patterns: {}",
-                            match missing_variants.len() {
-                                0 => format!("type `{}` is non-empty", pat_ty),
-                                1 => format!(
-                                    "pattern `{}` of type `{}` is not handled",
-                                    missing_variants[0].name, pat_ty,
-                                ),
-                                _ => format!(
-                                    "multiple patterns of type `{}` are not handled",
-                                    pat_ty
-                                ),
-                            }
-                        ),
-                    );
-                    err.help(
-                        "ensure that all possible cases are being handled, \
-                         possibly by adding wildcards or more match arms",
-                    );
-                    if let Some(sp) = def_span {
-                        err.span_label(sp, format!("`{}` defined here", pat_ty));
-                    }
-                    // point at the definition of non-covered enum variants
-                    for variant in &missing_variants {
-                        err.span_label(variant.span, "variant not covered");
-                    }
-                    err.emit();
-                }
-                // If the type *is* uninhabited, it's vacuously exhaustive
-                return;
-            }
-
+            // Fifth, check if the match is exhaustive.
             let scrut_ty = self.tables.node_type(scrut.hir_id);
-            check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id);
+            // Note: An empty match isn't the same as an empty matrix for diagnostics purposes,
+            // since an empty matrix can occur when there are arms, if those arms all have guards.
+            let is_empty_match = inlined_arms.is_empty();
+            check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id, is_empty_match);
         })
     }
 
@@ -390,7 +329,7 @@
     for (arm_index, (pat, hir_pat, has_guard)) in arms.iter().enumerate() {
         let v = PatStack::from_pattern(pat);
 
-        match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) {
+        match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id, true) {
             NotUseful => {
                 match source {
                     hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(),
@@ -478,7 +417,8 @@
     hir_id: HirId,
 ) -> Result<(), Vec<super::Pat<'tcx>>> {
     let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(ty));
-    match is_useful(cx, matrix, &PatStack::from_pattern(wild_pattern), ConstructWitness, hir_id) {
+    let v = PatStack::from_pattern(wild_pattern);
+    match is_useful(cx, matrix, &v, ConstructWitness, hir_id, true) {
         NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
         UsefulWithWitness(pats) => Err(if pats.is_empty() {
             bug!("Exhaustiveness check returned no witnesses")
@@ -495,25 +435,60 @@
     sp: Span,
     matrix: &Matrix<'p, 'tcx>,
     hir_id: HirId,
+    is_empty_match: bool,
 ) {
+    // In the absence of the `exhaustive_patterns` feature, empty matches are not detected by
+    // `is_useful` to exhaustively match uninhabited types, so we manually check here.
+    if is_empty_match && !cx.tcx.features().exhaustive_patterns {
+        let scrutinee_is_visibly_uninhabited = match scrut_ty.kind {
+            ty::Never => true,
+            ty::Adt(def, _) => {
+                def.is_enum()
+                    && def.variants.is_empty()
+                    && !cx.is_foreign_non_exhaustive_enum(scrut_ty)
+            }
+            _ => false,
+        };
+        if scrutinee_is_visibly_uninhabited {
+            // If the type *is* uninhabited, an empty match is vacuously exhaustive.
+            return;
+        }
+    }
+
     let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {
         Ok(_) => return,
         Err(err) => err,
     };
 
-    let joined_patterns = joined_uncovered_patterns(&witnesses);
-    let mut err = create_e0004(
-        cx.tcx.sess,
-        sp,
-        format!("non-exhaustive patterns: {} not covered", joined_patterns),
-    );
-    err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
+    let non_empty_enum = match scrut_ty.kind {
+        ty::Adt(def, _) => def.is_enum() && !def.variants.is_empty(),
+        _ => false,
+    };
+    // In the case of an empty match, replace the '`_` not covered' diagnostic with something more
+    // informative.
+    let mut err;
+    if is_empty_match && !non_empty_enum {
+        err = create_e0004(
+            cx.tcx.sess,
+            sp,
+            format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty),
+        );
+    } else {
+        let joined_patterns = joined_uncovered_patterns(&witnesses);
+        err = create_e0004(
+            cx.tcx.sess,
+            sp,
+            format!("non-exhaustive patterns: {} not covered", joined_patterns),
+        );
+        err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
+    };
+
     adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
     err.help(
         "ensure that all possible cases are being handled, \
          possibly by adding wildcards or more match arms",
-    )
-    .emit();
+    );
+    err.emit();
 }
 
 fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 92c7178..0086c3b 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -1154,13 +1154,7 @@
 ) -> Option<Ordering> {
     trace!("compare_const_vals: {:?}, {:?}", a, b);
 
-    let from_bool = |v: bool| {
-        if v {
-            Some(Ordering::Equal)
-        } else {
-            None
-        }
-    };
+    let from_bool = |v: bool| v.then_some(Ordering::Equal);
 
     let fallback = || from_bool(a == b);
 
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 9af47f3..653718c 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -312,7 +312,7 @@
         &self,
         instance: ty::InstanceDef<'tcx>,
         promoted: Option<mir::Promoted>,
-    ) -> InterpResult<'tcx, mir::ReadOnlyBodyCache<'tcx, 'tcx>> {
+    ) -> InterpResult<'tcx, mir::ReadOnlyBodyAndCache<'tcx, 'tcx>> {
         // do not continue if typeck errors occurred (can only occur in local crate)
         let did = instance.def_id();
         if did.is_local()
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index ad5df5a..67f0aed 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -112,6 +112,7 @@
         // `src/librustc/ty/constness.rs`
         match intrinsic_name {
             sym::caller_location => {
+                let span = self.find_closest_untracked_caller_location().unwrap_or(span);
                 let location = self.alloc_caller_location_for_span(span);
                 self.write_scalar(location.ptr, dest)?;
             }
diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs
index ecf4b7a..ec843ef 100644
--- a/src/librustc_mir/interpret/intrinsics/caller_location.rs
+++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs
@@ -6,6 +6,21 @@
 use crate::interpret::{Scalar, MemoryKind, MPlaceTy, intrinsics::{InterpCx, Machine}};
 
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
+    /// Walks up the callstack from the intrinsic's callsite, searching for the first frame which is
+    /// not `#[track_caller]`.
+    crate fn find_closest_untracked_caller_location(&self) -> Option<Span> {
+        let mut caller_span = None;
+        for next_caller in self.stack.iter().rev() {
+            if !next_caller.instance.def.requires_caller_location(*self.tcx) {
+                return caller_span;
+            }
+            caller_span = Some(next_caller.span);
+        }
+
+        caller_span
+    }
+
+    /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
     crate fn alloc_caller_location(
         &mut self,
         filename: Symbol,
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index ee7fb18..8f177ad 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -324,7 +324,7 @@
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Option<Pointer<M::PointerTag>>> {
-        let align = if M::CHECK_ALIGN { Some(align) } else { None };
+        let align = M::CHECK_ALIGN.then_some(align);
         self.check_ptr_access_align(sptr, size, align, CheckInAllocMsg::MemoryAccessTest)
     }
 
diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs
index 176b084..6800429 100644
--- a/src/librustc_mir/interpret/operator.rs
+++ b/src/librustc_mir/interpret/operator.rs
@@ -177,8 +177,8 @@
                 return Ok((Scalar::from_bool(op(&l, &r)), false, self.tcx.types.bool));
             }
             let op: Option<fn(i128, i128) -> (i128, bool)> = match bin_op {
-                Div if r == 0 => throw_panic!(DivisionByZero),
-                Rem if r == 0 => throw_panic!(RemainderByZero),
+                Div if r == 0 => throw_ub!(DivisionByZero),
+                Rem if r == 0 => throw_ub!(RemainderByZero),
                 Div => Some(i128::overflowing_div),
                 Rem => Some(i128::overflowing_rem),
                 Add => Some(i128::overflowing_add),
@@ -234,8 +234,8 @@
                     Add => u128::overflowing_add,
                     Sub => u128::overflowing_sub,
                     Mul => u128::overflowing_mul,
-                    Div if r == 0 => throw_panic!(DivisionByZero),
-                    Rem if r == 0 => throw_panic!(RemainderByZero),
+                    Div if r == 0 => throw_ub!(DivisionByZero),
+                    Rem if r == 0 => throw_ub!(RemainderByZero),
                     Div => u128::overflowing_div,
                     Rem => u128::overflowing_rem,
                     _ => bug!(),
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 902472d..42fbfec 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -384,10 +384,8 @@
             layout::FieldPlacement::Array { stride, .. } => {
                 let len = base.len(self)?;
                 if field >= len {
-                    // This can be violated because the index (field) can be a runtime value
-                    // provided by the user.
-                    debug!("tried to access element {} of array/slice with length {}", field, len);
-                    throw_panic!(BoundsCheck { len, index: field });
+                    // This can only be reached in ConstProp and non-rustc-MIR.
+                    throw_ub!(BoundsCheckFailed { len, index: field });
                 }
                 stride * field
             }
@@ -453,9 +451,15 @@
         base: MPlaceTy<'tcx, M::PointerTag>,
         from: u64,
         to: u64,
+        from_end: bool,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
-        assert!(from <= len - to);
+        let actual_to = if from_end {
+            assert!(from <= len - to);
+            len - to
+        } else {
+            to
+        };
 
         // Not using layout method because that works with usize, and does not work with slices
         // (that have count 0 in their layout).
@@ -466,7 +470,7 @@
         };
 
         // Compute meta and new layout
-        let inner_len = len - to - from;
+        let inner_len = actual_to - from;
         let (meta, ty) = match base.layout.ty.kind {
             // It is not nice to match on the type, but that seems to be the only way to
             // implement this.
@@ -530,8 +534,8 @@
                 self.mplace_field(base, index)?
             }
 
-            Subslice { from, to } =>
-                self.mplace_subslice(base, u64::from(from), u64::from(to))?,
+            Subslice { from, to, from_end } =>
+                self.mplace_subslice(base, u64::from(from), u64::from(to), from_end)?,
         })
     }
 
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index d749333..33ed69a 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -157,9 +157,9 @@
             }
 
             BinaryOp(bin_op, ref left, ref right) => {
-                let layout = if binop_left_homogeneous(bin_op) { Some(dest.layout) } else { None };
+                let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
                 let left = self.read_immediate(self.eval_operand(left, layout)?)?;
-                let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
+                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                 let right = self.read_immediate(self.eval_operand(right, layout)?)?;
                 self.binop_ignore_overflow(
                     bin_op,
@@ -172,7 +172,7 @@
             CheckedBinaryOp(bin_op, ref left, ref right) => {
                 // Due to the extra boolean in the result, we can never reuse the `dest.layout`.
                 let left = self.read_immediate(self.eval_operand(left, None)?)?;
-                let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
+                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                 let right = self.read_immediate(self.eval_operand(right, layout)?)?;
                 self.binop_with_overflow(
                     bin_op,
@@ -304,7 +304,9 @@
         if !self.stack.is_empty() {
             // This should change *something*
             debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb);
-            info!("// {:?}", self.frame().block);
+            if let Some(block) = self.frame().block {
+                info!("// executing {:?}", block);
+            }
         }
         Ok(())
     }
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index efa0d26..916ea3dc 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -140,7 +140,18 @@
         let fn_sig = drop_instance.ty(*self.tcx).fn_sig(*self.tcx);
         let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig);
         // The drop function takes `*mut T` where `T` is the type being dropped, so get that.
-        let ty = fn_sig.inputs()[0].builtin_deref(true).unwrap().ty;
+        let args = fn_sig.inputs();
+        if args.len() != 1 {
+            throw_ub_format!(
+                "drop fn should have 1 argument, but signature is {:?}", fn_sig
+            );
+        }
+        let ty = args[0].builtin_deref(true)
+            .ok_or_else(|| err_ub_format!(
+                "drop fn argument type {} is not a pointer type",
+                args[0]
+            ))?
+            .ty;
         Ok((drop_instance, ty))
     }
 
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index e358df2..1dbcfe5 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -22,28 +22,23 @@
 
 macro_rules! throw_validation_failure {
     ($what:expr, $where:expr, $details:expr) => {{
-        let where_ = path_format(&$where);
-        let where_ = if where_.is_empty() {
-            String::new()
-        } else {
-            format!(" at {}", where_)
-        };
-        throw_unsup!(ValidationFailure(format!(
-            "encountered {}{}, but expected {}",
-            $what, where_, $details,
-        )))
+        let mut msg = format!("encountered {}", $what);
+        let where_ = &$where;
+        if !where_.is_empty() {
+            msg.push_str(" at ");
+            write_path(&mut msg, where_);
+        }
+        write!(&mut msg, ", but expected {}", $details).unwrap();
+        throw_unsup!(ValidationFailure(msg))
     }};
     ($what:expr, $where:expr) => {{
-        let where_ = path_format(&$where);
-        let where_ = if where_.is_empty() {
-            String::new()
-        } else {
-            format!(" at {}", where_)
-        };
-        throw_unsup!(ValidationFailure(format!(
-            "encountered {}{}",
-            $what, where_,
-        )))
+        let mut msg = format!("encountered {}", $what);
+        let where_ = &$where;
+        if !where_.is_empty() {
+            msg.push_str(" at ");
+            write_path(&mut msg, where_);
+        }
+        throw_unsup!(ValidationFailure(msg))
     }};
 }
 
@@ -60,7 +55,7 @@
             Ok(x) => x,
             Err(_) => throw_validation_failure!($what, $where),
         }
-    }}
+    }};
 }
 
 /// We want to show a nice path to the invalid field for diagnostics,
@@ -113,10 +108,9 @@
 }
 
 /// Format a path
-fn path_format(path: &Vec<PathElem>) -> String {
+fn write_path(out: &mut String, path: &Vec<PathElem>) {
     use self::PathElem::*;
 
-    let mut out = String::new();
     for elem in path.iter() {
         match elem {
             Field(name) => write!(out, ".{}", name),
@@ -135,7 +129,6 @@
             DynDowncast => write!(out, ".<dyn-downcast>"),
         }.unwrap()
     }
-    out
 }
 
 // Test if a range that wraps at overflow contains `test`
@@ -428,7 +421,7 @@
                             err_unsup!(InvalidNullPointerUsage) =>
                                 throw_validation_failure!("NULL reference", self.path),
                             err_unsup!(AlignmentCheckFailed { required, has }) =>
-                                throw_validation_failure!(format!("unaligned reference \
+                                throw_validation_failure!(format_args!("unaligned reference \
                                     (required {} byte alignment but found {})",
                                     required.bytes(), has.bytes()), self.path),
                             err_unsup!(ReadBytesAsPointer) =>
@@ -519,7 +512,7 @@
         let value = try_validation!(value.not_undef(),
             value,
             self.path,
-            format!(
+            format_args!(
                 "something {}",
                 wrapping_range_format(&layout.valid_range, max_hi),
             )
@@ -532,7 +525,7 @@
                         throw_validation_failure!(
                             "a potentially NULL pointer",
                             self.path,
-                            format!(
+                            format_args!(
                                 "something that cannot possibly fail to be {}",
                                 wrapping_range_format(&layout.valid_range, max_hi)
                             )
@@ -545,7 +538,7 @@
                     throw_validation_failure!(
                         "a pointer",
                         self.path,
-                        format!(
+                        format_args!(
                             "something that cannot possibly fail to be {}",
                             wrapping_range_format(&layout.valid_range, max_hi)
                         )
@@ -562,7 +555,7 @@
             throw_validation_failure!(
                 bits,
                 self.path,
-                format!("something {}", wrapping_range_format(&layout.valid_range, max_hi))
+                format_args!("something {}", wrapping_range_format(&layout.valid_range, max_hi))
             )
         }
     }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index f4fb9a5..42b72b6 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -8,6 +8,7 @@
 #![feature(in_band_lifetimes)]
 #![feature(inner_deref)]
 #![feature(slice_patterns)]
+#![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
@@ -27,7 +28,6 @@
 #![feature(associated_type_bounds)]
 #![feature(range_is_empty)]
 #![feature(stmt_expr_attributes)]
-#![feature(bool_to_option)]
 #![feature(trait_alias)]
 #![feature(matches_macro)]
 
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 42f0877..591f220 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -761,11 +761,7 @@
             .iter()
             .map(|part| part.data.as_symbol());
 
-        let volatile_suffix = if volatile {
-            Some("volatile")
-        } else {
-            None
-        };
+        let volatile_suffix = volatile.then_some("volatile");
 
         name_builder.build_cgu_name(def_path.krate, components, volatile_suffix)
     }).clone()
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 5b208dd..47b0804 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -26,7 +26,7 @@
     providers.mir_shims = make_shim;
 }
 
-fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx BodyCache<'tcx> {
+fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx BodyAndCache<'tcx> {
     debug!("make_shim({:?})", instance);
 
     let mut result = match instance {
@@ -170,7 +170,7 @@
 
 fn build_drop_shim<'tcx>(
     tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>
-) -> BodyCache<'tcx> {
+) -> BodyAndCache<'tcx> {
     debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
 
     // Check if this is a generator, if so, return the drop glue for it
@@ -208,7 +208,7 @@
         sig.inputs().len(),
         span);
 
-    let mut body = BodyCache::new(body);
+    let mut body = BodyAndCache::new(body);
 
     if let Some(..) = ty {
         // The first argument (index 0), but add 1 for the return value.
@@ -322,7 +322,11 @@
 }
 
 /// Builds a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
-fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> BodyCache<'tcx> {
+fn build_clone_shim<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    self_ty: Ty<'tcx>,
+) -> BodyAndCache<'tcx> {
     debug!("build_clone_shim(def_id={:?})", def_id);
 
     let param_env = tcx.param_env(def_id);
@@ -351,7 +355,7 @@
         }
     };
 
-    BodyCache::new(builder.into_mir())
+    BodyAndCache::new(builder.into_mir())
 }
 
 struct CloneShimBuilder<'tcx> {
@@ -712,7 +716,7 @@
     rcvr_adjustment: Adjustment,
     call_kind: CallKind,
     untuple_args: Option<&[Ty<'tcx>]>,
-) -> BodyCache<'tcx> {
+) -> BodyAndCache<'tcx> {
     debug!("build_call_shim(instance={:?}, rcvr_adjustment={:?}, \
             call_kind={:?}, untuple_args={:?})",
            instance, rcvr_adjustment, call_kind, untuple_args);
@@ -853,10 +857,10 @@
     if let Abi::RustCall = sig.abi {
         body.spread_arg = Some(Local::new(sig.inputs().len()));
     }
-    BodyCache::new(body)
+    BodyAndCache::new(body)
 }
 
-pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyCache<'_> {
+pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyAndCache<'_> {
     debug_assert!(tcx.is_constructor(ctor_id));
 
     let span = tcx.hir().span_if_local(ctor_id)
@@ -940,7 +944,7 @@
         |_, _| Ok(()),
     );
 
-    let mut body = BodyCache::new(body);
+    let mut body = BodyAndCache::new(body);
     body.ensure_predecessors();
     tcx.arena.alloc(body)
 }
diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs
index 35238e2..d1832eb 100644
--- a/src/librustc_mir/transform/add_call_guards.rs
+++ b/src/librustc_mir/transform/add_call_guards.rs
@@ -32,14 +32,14 @@
 
 impl<'tcx> MirPass<'tcx> for AddCallGuards {
     fn run_pass(
-        &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+        &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>
     ) {
         self.add_call_guards(body);
     }
 }
 
 impl AddCallGuards {
-    pub fn add_call_guards(&self, body: &mut BodyCache<'_>) {
+    pub fn add_call_guards(&self, body: &mut BodyAndCache<'_>) {
         let pred_count: IndexVec<_, _> = body.predecessors().iter().map(|ps| ps.len()).collect();
 
         // We need a place to store the new blocks generated
diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
index 98c6a5e..861e7fe 100644
--- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs
+++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
@@ -40,14 +40,14 @@
 pub struct AddMovesForPackedDrops;
 
 impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span);
         add_moves_for_packed_drops(tcx, body, src.def_id());
     }
 }
 
 pub fn add_moves_for_packed_drops<'tcx>(
-    tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>, def_id: DefId
+    tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>, def_id: DefId
 ) {
     let patch = add_moves_for_packed_drops_patch(tcx, body, def_id);
     patch.apply(body);
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index e6ad37a..dc21c67 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -59,7 +59,7 @@
 }
 
 impl<'tcx> MirPass<'tcx> for AddRetag {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         if !tcx.sess.opts.debugging_opts.mir_emit_retag {
             return;
         }
diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs
index 7095b3f..89672e8 100644
--- a/src/librustc_mir/transform/check_consts/mod.rs
+++ b/src/librustc_mir/transform/check_consts/mod.rs
@@ -20,7 +20,7 @@
 /// Information about the item currently being const-checked, as well as a reference to the global
 /// context.
 pub struct Item<'mir, 'tcx> {
-    pub body: mir::ReadOnlyBodyCache<'mir, 'tcx>,
+    pub body: mir::ReadOnlyBodyAndCache<'mir, 'tcx>,
     pub tcx: TyCtxt<'tcx>,
     pub def_id: DefId,
     pub param_env: ty::ParamEnv<'tcx>,
@@ -31,7 +31,7 @@
     pub fn new(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        body: mir::ReadOnlyBodyCache<'mir, 'tcx>,
+        body: mir::ReadOnlyBodyAndCache<'mir, 'tcx>,
     ) -> Self {
         let param_env = tcx.param_env(def_id);
         let const_kind = ConstKind::for_item(tcx, def_id);
@@ -77,7 +77,12 @@
         let mode = match tcx.hir().body_owner_kind(hir_id) {
             HirKind::Closure => return None,
 
-            HirKind::Fn if tcx.is_const_fn(def_id) => ConstKind::ConstFn,
+            // Note: this is deliberately checking for `is_const_fn_raw`, as the `is_const_fn`
+            // checks take into account the `rustc_const_unstable` attribute combined with enabled
+            // feature gates. Otherwise, const qualification would _not check_ whether this
+            // function body follows the `const fn` rules, as an unstable `const fn` would
+            // be considered "not const". More details are available in issue #67053.
+            HirKind::Fn if tcx.is_const_fn_raw(def_id) => ConstKind::ConstFn,
             HirKind::Fn => return None,
 
             HirKind::Const => ConstKind::Const,
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index aec3cf0..393ae94 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -1,7 +1,6 @@
 //! Concrete error types for all operations which may be invalid in a certain const context.
 
 use rustc::hir::def_id::DefId;
-use rustc::mir::BorrowKind;
 use rustc::session::config::nightly_options;
 use rustc::ty::TyCtxt;
 use syntax::feature_gate::feature_err;
@@ -181,38 +180,53 @@
 }
 
 #[derive(Debug)]
-pub struct MutBorrow(pub BorrowKind);
-impl NonConstOp for MutBorrow {
+pub struct CellBorrow;
+impl NonConstOp for CellBorrow {
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
-        let kind = self.0;
-        if let BorrowKind::Mut { .. } = kind {
-            let mut err = struct_span_err!(item.tcx.sess, span, E0017,
-                                           "references in {}s may only refer \
-                                            to immutable values", item.const_kind());
-            err.span_label(span, format!("{}s require immutable values",
-                                                item.const_kind()));
-            if item.tcx.sess.teach(&err.get_code().unwrap()) {
-                err.note("References in statics and constants may only refer \
-                          to immutable values.\n\n\
-                          Statics are shared everywhere, and if they refer to \
-                          mutable data one might violate memory safety since \
-                          holding multiple mutable references to shared data \
-                          is not allowed.\n\n\
-                          If you really want global mutable state, try using \
-                          static mut or a global UnsafeCell.");
-            }
-            err.emit();
-        } else {
-            span_err!(item.tcx.sess, span, E0492,
-                      "cannot borrow a constant which may contain \
-                       interior mutability, create a static instead");
+        span_err!(item.tcx.sess, span, E0492,
+            "cannot borrow a constant which may contain \
+            interior mutability, create a static instead");
+    }
+}
+
+#[derive(Debug)]
+pub struct MutBorrow;
+impl NonConstOp for MutBorrow {
+    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
+        Some(tcx.features().const_mut_refs)
+    }
+
+    fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
+        let mut err = feature_err(
+            &item.tcx.sess.parse_sess,
+            sym::const_mut_refs,
+            span,
+            &format!("references in {}s may only refer \
+                      to immutable values", item.const_kind())
+        );
+        err.span_label(span, format!("{}s require immutable values",
+                                            item.const_kind()));
+        if item.tcx.sess.teach(&err.get_code().unwrap()) {
+            err.note("References in statics and constants may only refer \
+                      to immutable values.\n\n\
+                      Statics are shared everywhere, and if they refer to \
+                      mutable data one might violate memory safety since \
+                      holding multiple mutable references to shared data \
+                      is not allowed.\n\n\
+                      If you really want global mutable state, try using \
+                      static mut or a global UnsafeCell.");
         }
+        err.emit();
     }
 }
 
 #[derive(Debug)]
 pub struct MutDeref;
-impl NonConstOp for MutDeref {}
+impl NonConstOp for MutDeref {
+    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
+        Some(tcx.features().const_mut_refs)
+    }
+}
 
 #[derive(Debug)]
 pub struct Panic;
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index f44bac1..6261315 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -40,7 +40,7 @@
         let results =
             dataflow::Engine::new(item.tcx, &item.body, item.def_id, dead_unwinds, analysis)
                 .iterate_to_fixpoint();
-        let cursor = dataflow::ResultsCursor::new(item.body.body(), results);
+        let cursor = dataflow::ResultsCursor::new(*item.body, results);
 
         let mut in_any_value_of_ty = BitSet::new_empty(item.body.local_decls.len());
         for (local, decl) in item.body.local_decls.iter_enumerated() {
@@ -175,13 +175,13 @@
             item.def_id,
             &item.tcx.get_attrs(item.def_id),
             &dead_unwinds,
-            old_dataflow::IndirectlyMutableLocals::new(item.tcx, item.body.body(), item.param_env),
+            old_dataflow::IndirectlyMutableLocals::new(item.tcx, *item.body, item.param_env),
             |_, local| old_dataflow::DebugFormatted::new(&local),
         );
 
         let indirectly_mutable = old_dataflow::DataflowResultsCursor::new(
             indirectly_mutable,
-            item.body.body(),
+            *item.body,
         );
 
         let qualifs = Qualifs {
@@ -359,7 +359,11 @@
                 };
 
                 if !is_allowed {
-                    self.check_op(ops::MutBorrow(kind));
+                    if let BorrowKind::Mut{ .. } = kind {
+                        self.check_op(ops::MutBorrow);
+                    } else {
+                        self.check_op(ops::CellBorrow);
+                    }
                 }
             }
 
@@ -384,7 +388,11 @@
                 );
 
                 if borrowed_place_has_mut_interior {
-                    self.check_op(ops::MutBorrow(kind));
+                    if let BorrowKind::Mut{ .. } = kind {
+                        self.check_op(ops::MutBorrow);
+                    } else {
+                        self.check_op(ops::CellBorrow);
+                    }
                 }
             }
 
@@ -451,7 +459,6 @@
             }
         }
     }
-
     fn visit_projection_elem(
         &mut self,
         place_base: &PlaceBase<'tcx>,
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 2c45dcf..284285c 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -658,7 +658,7 @@
     let mut unsafe_blocks: Vec<_> = unsafe_blocks.into_iter().collect();
     unsafe_blocks.sort_by_cached_key(|(hir_id, _)| tcx.hir().hir_to_node_id(*hir_id));
     let used_unsafe: FxHashSet<_> = unsafe_blocks.iter()
-        .flat_map(|&&(id, used)| if used { Some(id) } else { None })
+        .flat_map(|&&(id, used)| used.then_some(id))
         .collect();
     for &(block_id, is_used) in unsafe_blocks {
         if !is_used {
diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs
index d9dd7c9..34519bc 100644
--- a/src/librustc_mir/transform/cleanup_post_borrowck.rs
+++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs
@@ -16,7 +16,7 @@
 //! [`FakeRead`]: rustc::mir::StatementKind::FakeRead
 //! [`Nop`]: rustc::mir::StatementKind::Nop
 
-use rustc::mir::{BodyCache, BorrowKind, Rvalue, Location};
+use rustc::mir::{BodyAndCache, BorrowKind, Rvalue, Location};
 use rustc::mir::{Statement, StatementKind};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
@@ -30,7 +30,7 @@
 
 impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements {
     fn run_pass(
-        &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+        &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>
     ) {
         let mut delete = DeleteNonCodegenStatements { tcx };
         delete.visit_body(body);
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 95de635..aff91ac 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -7,9 +7,9 @@
 use rustc::hir::def::DefKind;
 use rustc::hir::def_id::DefId;
 use rustc::mir::{
-    AggregateKind, Constant, Location, Place, PlaceBase, Body, BodyCache, Operand, Local, UnOp,
-    Rvalue, StatementKind, Statement, LocalKind, TerminatorKind, Terminator,  ClearCrossCrate,
-    SourceInfo, BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, ReadOnlyBodyCache,
+    AggregateKind, Constant, Location, Place, PlaceBase, Body, BodyAndCache, Operand, Local, UnOp,
+    Rvalue, StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate,
+    SourceInfo, BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, ReadOnlyBodyAndCache,
     read_only, RETURN_PLACE
 };
 use rustc::mir::visit::{
@@ -43,7 +43,7 @@
 
 impl<'tcx> MirPass<'tcx> for ConstProp {
     fn run_pass(
-        &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+        &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>
     ) {
         // will be evaluated by miri and produce its errors there
         if source.promoted.is_some() {
@@ -296,7 +296,7 @@
 
 impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     fn new(
-        body: ReadOnlyBodyCache<'_, 'tcx>,
+        body: ReadOnlyBodyAndCache<'_, 'tcx>,
         dummy_body: &'mir Body<'tcx>,
         tcx: TyCtxt<'tcx>,
         source: MirSource<'tcx>,
@@ -636,19 +636,45 @@
                     ScalarMaybeUndef::Scalar(one),
                     ScalarMaybeUndef::Scalar(two)
                 ) => {
+                    // Found a value represented as a pair. For now only do cont-prop if type of
+                    // Rvalue is also a pair with two scalars. The more general case is more
+                    // complicated to implement so we'll do it later.
                     let ty = &value.layout.ty.kind;
+                    // Only do it for tuples
                     if let ty::Tuple(substs) = ty {
-                        *rval = Rvalue::Aggregate(
-                            Box::new(AggregateKind::Tuple),
-                            vec![
-                                self.operand_from_scalar(
-                                    one, substs[0].expect_ty(), source_info.span
-                                ),
-                                self.operand_from_scalar(
-                                    two, substs[1].expect_ty(), source_info.span
-                                ),
-                            ],
-                        );
+                        // Only do it if tuple is also a pair with two scalars
+                        if substs.len() == 2 {
+                            let opt_ty1_ty2 = self.use_ecx(source_info, |this| {
+                                let ty1 = substs[0].expect_ty();
+                                let ty2 = substs[1].expect_ty();
+                                let ty_is_scalar = |ty| {
+                                    this.ecx
+                                        .layout_of(ty)
+                                        .ok()
+                                        .map(|ty| ty.details.abi.is_scalar())
+                                        == Some(true)
+                                };
+                                if ty_is_scalar(ty1) && ty_is_scalar(ty2) {
+                                    Ok(Some((ty1, ty2)))
+                                } else {
+                                    Ok(None)
+                                }
+                            });
+
+                            if let Some(Some((ty1, ty2))) = opt_ty1_ty2 {
+                                *rval = Rvalue::Aggregate(
+                                    Box::new(AggregateKind::Tuple),
+                                    vec![
+                                        self.operand_from_scalar(
+                                            one, ty1, source_info.span
+                                        ),
+                                        self.operand_from_scalar(
+                                            two, ty2, source_info.span
+                                        ),
+                                    ],
+                                );
+                            }
+                        }
                     }
                 },
                 _ => { }
@@ -690,7 +716,7 @@
 
 impl CanConstProp {
     /// returns true if `local` can be propagated
-    fn check(body: ReadOnlyBodyCache<'_, '_>) -> IndexVec<Local, bool> {
+    fn check(body: ReadOnlyBodyAndCache<'_, '_>) -> IndexVec<Local, bool> {
         let mut cpv = CanConstProp {
             can_const_prop: IndexVec::from_elem(true, &body.local_decls),
             found_assignment: IndexVec::from_elem(false, &body.local_decls),
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index 5e4caf2..272f6e9 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -20,7 +20,7 @@
 //! future.
 
 use rustc::mir::{
-    Constant, Local, LocalKind, Location, Place, Body, BodyCache, Operand, Rvalue,
+    Constant, Local, LocalKind, Location, Place, Body, BodyAndCache, Operand, Rvalue,
     StatementKind, read_only
 };
 use rustc::mir::visit::MutVisitor;
@@ -32,7 +32,7 @@
 
 impl<'tcx> MirPass<'tcx> for CopyPropagation {
     fn run_pass(
-        &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+        &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>
     ) {
         // We only run when the MIR optimization level is > 1.
         // This avoids a slow pass, and messing up debug info.
@@ -250,7 +250,7 @@
     }
 
     fn perform(self,
-               body: &mut BodyCache<'tcx>,
+               body: &mut BodyAndCache<'tcx>,
                def_use_analysis: &DefUseAnalysis,
                dest_local: Local,
                location: Location,
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs
index 933936e..cd77c9c 100644
--- a/src/librustc_mir/transform/deaggregator.rs
+++ b/src/librustc_mir/transform/deaggregator.rs
@@ -7,7 +7,7 @@
 
 impl<'tcx> MirPass<'tcx> for Deaggregator {
     fn run_pass(
-        &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+        &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>
     ) {
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
         let local_decls = &*local_decls;
diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs
index 13b3bb6..221ced3 100644
--- a/src/librustc_mir/transform/dump_mir.rs
+++ b/src/librustc_mir/transform/dump_mir.rs
@@ -5,7 +5,7 @@
 use std::fs::File;
 use std::io;
 
-use rustc::mir::{Body, BodyCache};
+use rustc::mir::{Body, BodyAndCache};
 use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::ty::TyCtxt;
 use crate::transform::{MirPass, MirSource};
@@ -19,7 +19,7 @@
     }
 
     fn run_pass(
-        &self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut BodyCache<'tcx>
+        &self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut BodyAndCache<'tcx>
     ) {}
 }
 
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 42daba9..1cacf1f 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -21,12 +21,12 @@
 pub struct ElaborateDrops;
 
 impl<'tcx> MirPass<'tcx> for ElaborateDrops {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         debug!("elaborate_drops({:?} @ {:?})", src, body.span);
 
         let def_id = src.def_id();
         let param_env = tcx.param_env(src.def_id()).with_reveal_all();
-        let move_data = match MoveData::gather_moves(body, tcx) {
+        let move_data = match MoveData::gather_moves(body, tcx, param_env) {
             Ok(move_data) => move_data,
             Err(_) => bug!("No `move_errors` should be allowed in MIR borrowck"),
         };
@@ -234,12 +234,11 @@
 
     fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path> {
         dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
-            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false } => {
+            ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
+                debug_assert!(size == *min_length, "min_length should be exact for arrays");
+                assert!(!from_end, "from_end should not be used for array element ConstantIndex");
                 *offset == index
             }
-            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: true } => {
-                size - offset == index
-            }
             _ => false,
         })
     }
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 882e674..1eef3f2 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -62,7 +62,7 @@
 pub struct EraseRegions;
 
 impl<'tcx> MirPass<'tcx> for EraseRegions {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         EraseRegionsVisitor::new(tcx).visit_body(body);
     }
 }
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index e55737e..3d15d04 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -378,7 +378,7 @@
 fn make_generator_state_argument_indirect<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
 ) {
     let gen_ty = body.local_decls.raw[1].ty;
 
@@ -401,7 +401,7 @@
     DerefArgVisitor { tcx }.visit_body(body);
 }
 
-fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) {
+fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>) {
     let ref_gen_ty = body.local_decls.raw[1].ty;
 
     let pin_did = tcx.lang_items().pin_type().unwrap();
@@ -418,7 +418,7 @@
 
 fn replace_result_variable<'tcx>(
     ret_ty: Ty<'tcx>,
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
     tcx: TyCtxt<'tcx>,
 ) -> Local {
     let source_info = source_info(body);
@@ -481,7 +481,7 @@
 
 fn locals_live_across_suspend_points(
     tcx: TyCtxt<'tcx>,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
     source: MirSource<'tcx>,
     movable: bool,
 ) -> LivenessInfo {
@@ -751,7 +751,7 @@
     upvars: &Vec<Ty<'tcx>>,
     interior: Ty<'tcx>,
     movable: bool,
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
 ) -> (
     FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
     GeneratorLayout<'tcx>,
@@ -830,7 +830,7 @@
 }
 
 fn insert_switch<'tcx>(
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
     cases: Vec<(usize, BasicBlock)>,
     transform: &TransformVisitor<'tcx>,
     default: TerminatorKind<'tcx>,
@@ -862,7 +862,7 @@
 }
 
 fn elaborate_generator_drops<'tcx>(
-    tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut BodyCache<'tcx>
+    tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut BodyAndCache<'tcx>
 ) {
     use crate::util::elaborate_drops::{elaborate_drop, Unwind};
     use crate::util::patch::MirPatch;
@@ -928,9 +928,9 @@
     def_id: DefId,
     source: MirSource<'tcx>,
     gen_ty: Ty<'tcx>,
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
     drop_clean: BasicBlock,
-) -> BodyCache<'tcx> {
+) -> BodyAndCache<'tcx> {
     let mut body = body.clone();
 
     let source_info = source_info(&body);
@@ -997,7 +997,7 @@
 }
 
 fn insert_term_block<'tcx>(
-    body: &mut BodyCache<'tcx>, kind: TerminatorKind<'tcx>
+    body: &mut BodyAndCache<'tcx>, kind: TerminatorKind<'tcx>
 ) -> BasicBlock {
     let term_block = BasicBlock::new(body.basic_blocks().len());
     let source_info = source_info(body);
@@ -1014,7 +1014,7 @@
 
 fn insert_panic_block<'tcx>(
     tcx: TyCtxt<'tcx>,
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
     message: AssertMessage<'tcx>,
 ) -> BasicBlock {
     let assert_block = BasicBlock::new(body.basic_blocks().len());
@@ -1048,7 +1048,7 @@
     transform: TransformVisitor<'tcx>,
     def_id: DefId,
     source: MirSource<'tcx>,
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
 ) {
     // Poison the generator when it unwinds
     for block in body.basic_blocks_mut() {
@@ -1101,7 +1101,7 @@
     }
 }
 
-fn insert_clean_drop(body: &mut BodyCache<'_>) -> BasicBlock {
+fn insert_clean_drop(body: &mut BodyAndCache<'_>) -> BasicBlock {
     let return_block = insert_term_block(body, TerminatorKind::Return);
 
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
@@ -1125,7 +1125,7 @@
 }
 
 fn create_cases<'tcx, F>(
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
     transform: &TransformVisitor<'tcx>,
     target: F,
 ) -> Vec<(usize, BasicBlock)>
@@ -1170,7 +1170,7 @@
 
 impl<'tcx> MirPass<'tcx> for StateTransform {
     fn run_pass(
-        &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+        &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>
     ) {
         let yield_ty = if let Some(yield_ty) = body.yield_ty {
             yield_ty
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 79cb7fb..9763913 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -39,7 +39,7 @@
 
 impl<'tcx> MirPass<'tcx> for Inline {
     fn run_pass(
-        &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+        &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>
     ) {
         if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
             Inliner { tcx, source }.run_pass(body);
@@ -53,7 +53,7 @@
 }
 
 impl Inliner<'tcx> {
-    fn run_pass(&self, caller_body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, caller_body: &mut BodyAndCache<'tcx>) {
         // Keep a queue of callsites to try inlining on. We take
         // advantage of the fact that queries detect cycles here to
         // allow us to try and fetch the fully optimized MIR of a
@@ -230,6 +230,11 @@
 
         let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee);
 
+        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) {
+            debug!("`#[track_caller]` present - not inlining");
+            return false;
+        }
+
         let hinted = match codegen_fn_attrs.inline {
             // Just treat inline(always) as a hint for now,
             // there are cases that prevent inlining that we
@@ -380,8 +385,8 @@
 
     fn inline_call(&self,
                    callsite: CallSite<'tcx>,
-                   caller_body: &mut BodyCache<'tcx>,
-                   mut callee_body: BodyCache<'tcx>) -> bool {
+                   caller_body: &mut BodyAndCache<'tcx>,
+                   mut callee_body: BodyAndCache<'tcx>) -> bool {
         let terminator = caller_body[callsite.bb].terminator.take().unwrap();
         match terminator.kind {
             // FIXME: Handle inlining of diverging calls
@@ -517,7 +522,7 @@
         &self,
         args: Vec<Operand<'tcx>>,
         callsite: &CallSite<'tcx>,
-        caller_body: &mut BodyCache<'tcx>,
+        caller_body: &mut BodyAndCache<'tcx>,
     ) -> Vec<Local> {
         let tcx = self.tcx;
 
@@ -590,7 +595,7 @@
         &self,
         arg: Operand<'tcx>,
         callsite: &CallSite<'tcx>,
-        caller_body: &mut BodyCache<'tcx>,
+        caller_body: &mut BodyAndCache<'tcx>,
     ) -> Local {
         // FIXME: Analysis of the usage of the arguments to avoid
         // unnecessary temporaries.
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index bd237b5..eca1b59 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -1,7 +1,7 @@
 //! Performs various peephole optimizations.
 
 use rustc::mir::{
-    Constant, Location, Place, PlaceBase, PlaceRef, Body, BodyCache, Operand, ProjectionElem,
+    Constant, Location, Place, PlaceBase, PlaceRef, Body, BodyAndCache, Operand, ProjectionElem,
     Rvalue, Local, read_only
 };
 use rustc::mir::visit::{MutVisitor, Visitor};
@@ -14,7 +14,7 @@
 pub struct InstCombine;
 
 impl<'tcx> MirPass<'tcx> for InstCombine {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         // We only run when optimizing MIR (at any level).
         if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
             return
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index df4cb76..2e1a08a 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -1,7 +1,7 @@
 use crate::{build, shim};
 use rustc_index::vec::IndexVec;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::mir::{BodyCache, MirPhase, Promoted, ConstQualifs};
+use rustc::mir::{BodyAndCache, MirPhase, Promoted, ConstQualifs};
 use rustc::ty::{TyCtxt, InstanceDef, TypeFoldable};
 use rustc::ty::query::Providers;
 use rustc::ty::steal::Steal;
@@ -35,7 +35,6 @@
 pub mod const_prop;
 pub mod generator;
 pub mod inline;
-pub mod uniform_array_move_out;
 pub mod uninhabited_enum_branching;
 
 pub(crate) fn provide(providers: &mut Providers<'_>) {
@@ -97,7 +96,7 @@
     tcx.arena.alloc(set)
 }
 
-fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyCache<'_>> {
+fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyAndCache<'_>> {
     let mir = build::mir_build(tcx, def_id);
     tcx.alloc_steal_mir(mir)
 }
@@ -144,12 +143,12 @@
         default_name::<Self>()
     }
 
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>);
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>);
 }
 
 pub fn run_passes(
     tcx: TyCtxt<'tcx>,
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
     instance: InstanceDef<'tcx>,
     promoted: Option<Promoted>,
     mir_phase: MirPhase,
@@ -220,7 +219,7 @@
     validator.qualifs_in_return_place().into()
 }
 
-fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyCache<'_>> {
+fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyAndCache<'_>> {
     // Unsafety check uses the raw mir, so make sure it is run
     let _ = tcx.unsafety_check_result(def_id);
 
@@ -229,7 +228,6 @@
         // What we need to do constant evaluation.
         &simplify::SimplifyCfg::new("initial"),
         &rustc_peek::SanityCheck,
-        &uniform_array_move_out::UniformArrayMoveOut,
     ]);
     body.ensure_predecessors();
     tcx.alloc_steal_mir(body)
@@ -238,7 +236,7 @@
 fn mir_validated(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
-) -> (&'tcx Steal<BodyCache<'tcx>>, &'tcx Steal<IndexVec<Promoted, BodyCache<'tcx>>>) {
+) -> (&'tcx Steal<BodyAndCache<'tcx>>, &'tcx Steal<IndexVec<Promoted, BodyAndCache<'tcx>>>) {
     // Ensure that we compute the `mir_const_qualif` for constants at
     // this point, before we steal the mir-const result.
     let _ = tcx.mir_const_qualif(def_id);
@@ -257,7 +255,7 @@
 
 fn run_optimization_passes<'tcx>(
     tcx: TyCtxt<'tcx>,
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
     def_id: DefId,
     promoted: Option<Promoted>,
 ) {
@@ -294,7 +292,6 @@
         // Optimizations begin.
         &uninhabited_enum_branching::UninhabitedEnumBranching,
         &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"),
-        &uniform_array_move_out::RestoreSubsliceArrayMoveOut::new(tcx),
         &inline::Inline,
 
         // Lowering generator control-flow and variables
@@ -319,7 +316,7 @@
     ]);
 }
 
-fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> {
+fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyAndCache<'_> {
     if tcx.is_constructor(def_id) {
         // There's no reason to run all of the MIR passes on constructors when
         // we can just output the MIR we want directly. This also saves const
@@ -339,7 +336,7 @@
     tcx.arena.alloc(body)
 }
 
-fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec<Promoted, BodyCache<'_>> {
+fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec<Promoted, BodyAndCache<'_>> {
     if tcx.is_constructor(def_id) {
         return tcx.intern_promoted(IndexVec::new());
     }
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
index 5e1d29d..d4fe72f 100644
--- a/src/librustc_mir/transform/no_landing_pads.rs
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -17,12 +17,12 @@
 }
 
 impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         no_landing_pads(tcx, body)
     }
 }
 
-pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) {
+pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>) {
     if tcx.sess.no_landing_pads() {
         NoLandingPads::new(tcx).visit_body(body);
     }
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index c758ccf..4c72319 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -41,11 +41,11 @@
 /// newly created `StaticKind::Promoted`.
 #[derive(Default)]
 pub struct PromoteTemps<'tcx> {
-    pub promoted_fragments: Cell<IndexVec<Promoted, BodyCache<'tcx>>>,
+    pub promoted_fragments: Cell<IndexVec<Promoted, BodyAndCache<'tcx>>>,
 }
 
 impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         // There's not really any point in promoting errorful MIR.
         //
         // This does not include MIR that failed const-checking, which we still try to promote.
@@ -742,7 +742,7 @@
 // FIXME(eddyb) remove the differences for promotability in `static`, `const`, `const fn`.
 pub fn validate_candidates(
     tcx: TyCtxt<'tcx>,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
     def_id: DefId,
     temps: &IndexVec<Local, TempState>,
     candidates: &[Candidate],
@@ -775,8 +775,8 @@
 
 struct Promoter<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    source: &'a mut BodyCache<'tcx>,
-    promoted: BodyCache<'tcx>,
+    source: &'a mut BodyAndCache<'tcx>,
+    promoted: BodyAndCache<'tcx>,
     temps: &'a mut IndexVec<Local, TempState>,
 
     /// If true, all nested temps are also kept in the
@@ -924,7 +924,7 @@
         def_id: DefId,
         candidate: Candidate,
         next_promoted_id: usize,
-    ) -> Option<BodyCache<'tcx>> {
+    ) -> Option<BodyAndCache<'tcx>> {
         let mut operand = {
             let promoted = &mut self.promoted;
             let promoted_id = Promoted::new(next_promoted_id);
@@ -1045,11 +1045,11 @@
 
 pub fn promote_candidates<'tcx>(
     def_id: DefId,
-    body: &mut BodyCache<'tcx>,
+    body: &mut BodyAndCache<'tcx>,
     tcx: TyCtxt<'tcx>,
     mut temps: IndexVec<Local, TempState>,
     candidates: Vec<Candidate>,
-) -> IndexVec<Promoted, BodyCache<'tcx>> {
+) -> IndexVec<Promoted, BodyAndCache<'tcx>> {
     // Visit candidates in reverse, in case they're nested.
     debug!("promote_candidates({:?})", candidates);
 
@@ -1081,7 +1081,7 @@
         ).collect();
 
         let promoter = Promoter {
-            promoted: BodyCache::new(Body::new(
+            promoted: BodyAndCache::new(Body::new(
                 IndexVec::new(),
                 // FIXME: maybe try to filter this to avoid blowing up
                 // memory usage?
@@ -1150,7 +1150,7 @@
 crate fn should_suggest_const_in_array_repeat_expressions_attribute<'tcx>(
     tcx: TyCtxt<'tcx>,
     mir_def_id: DefId,
-    body: ReadOnlyBodyCache<'_, 'tcx>,
+    body: ReadOnlyBodyAndCache<'_, 'tcx>,
     operand: &Operand<'tcx>,
 ) -> bool {
     let mut rpo = traversal::reverse_postorder(&body);
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 3030d2e..1c95155 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -79,10 +79,14 @@
 fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult {
     for ty in ty.walk() {
         match ty.kind {
-            ty::Ref(_, _, hir::Mutability::Mutable) => return Err((
-                span,
-                "mutable references in const fn are unstable".into(),
-            )),
+            ty::Ref(_, _, hir::Mutability::Mutable) => {
+                if !feature_allowed(tcx, fn_def_id, sym::const_mut_refs) {
+                    return Err((
+                        span,
+                        "mutable references in const fn are unstable".into(),
+                    ))
+                }
+            }
             ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
             ty::FnPtr(..) => {
                 if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
@@ -216,7 +220,7 @@
         }
 
         | StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _)
-        if !tcx.features().const_if_match
+        if !feature_allowed(tcx, def_id, sym::const_if_match)
         => {
             Err((span, "loops and conditional expressions are not stable in const fn".into()))
         }
@@ -268,7 +272,7 @@
     while let &[ref proj_base @ .., elem] = cursor {
         cursor = proj_base;
         match elem {
-            ProjectionElem::Downcast(..) if !tcx.features().const_if_match
+            ProjectionElem::Downcast(..) if !feature_allowed(tcx, def_id, sym::const_if_match)
                 => return Err((span, "`match` or `if let` in `const fn` is unstable".into())),
             ProjectionElem::Downcast(_symbol, _variant_index) => {}
 
@@ -325,7 +329,7 @@
 
         | TerminatorKind::FalseEdges { .. }
         | TerminatorKind::SwitchInt { .. }
-        if !tcx.features().const_if_match
+        if !feature_allowed(tcx, def_id, sym::const_if_match)
         => Err((
             span,
             "loops and conditional expressions are not stable in const fn".into(),
@@ -337,7 +341,7 @@
         }
 
         // FIXME(ecstaticmorse): We probably want to allow `Unreachable` unconditionally.
-        TerminatorKind::Unreachable if tcx.features().const_if_match => Ok(()),
+        TerminatorKind::Unreachable if feature_allowed(tcx, def_id, sym::const_if_match) => Ok(()),
 
         | TerminatorKind::Abort | TerminatorKind::Unreachable => {
             Err((span, "const fn with unreachable code is not stable".into()))
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index c636aba..5799d0c 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -9,7 +9,7 @@
 /// code for these.
 pub struct RemoveNoopLandingPads;
 
-pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) {
+pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>) {
     if tcx.sess.no_landing_pads() {
         return
     }
@@ -19,7 +19,7 @@
 }
 
 impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         remove_noop_landing_pads(tcx, body);
     }
 }
@@ -84,7 +84,7 @@
         }
     }
 
-    fn remove_nop_landing_pads(&self, body: &mut BodyCache<'_>) {
+    fn remove_nop_landing_pads(&self, body: &mut BodyAndCache<'_>) {
         // make sure there's a single resume block
         let resume_block = {
             let patch = MirPatch::new(body);
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 794ced1..4345fc6 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -5,7 +5,7 @@
 
 use rustc::ty::{self, TyCtxt, Ty};
 use rustc::hir::def_id::DefId;
-use rustc::mir::{self, Body, BodyCache, Location, Local};
+use rustc::mir::{self, Body, BodyAndCache, Location, Local};
 use rustc_index::bit_set::BitSet;
 use crate::transform::{MirPass, MirSource};
 
@@ -26,7 +26,7 @@
 pub struct SanityCheck;
 
 impl<'tcx> MirPass<'tcx> for SanityCheck {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         let def_id = src.def_id();
         if !tcx.has_attr(def_id, sym::rustc_mir) {
             debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
@@ -37,7 +37,7 @@
 
         let attributes = tcx.get_attrs(def_id);
         let param_env = tcx.param_env(def_id);
-        let move_data = MoveData::gather_moves(body, tcx).unwrap();
+        let move_data = MoveData::gather_moves(body, tcx, param_env).unwrap();
         let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
         let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
         let flow_inits =
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index 900752d..628ac72 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -29,7 +29,7 @@
 
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc::ty::TyCtxt;
+use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext, MutatingUseContext};
 use std::borrow::Cow;
@@ -43,7 +43,7 @@
     }
 }
 
-pub fn simplify_cfg(body: &mut BodyCache<'_>) {
+pub fn simplify_cfg(body: &mut BodyAndCache<'_>) {
     CfgSimplifier::new(body).simplify();
     remove_dead_blocks(body);
 
@@ -57,7 +57,7 @@
     }
 
     fn run_pass(
-        &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+        &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>
     ) {
         debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body);
         simplify_cfg(body);
@@ -70,7 +70,7 @@
 }
 
 impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
-    pub fn new(body: &'a mut BodyCache<'tcx>) -> Self {
+    pub fn new(body: &'a mut BodyAndCache<'tcx>) -> Self {
         let mut pred_count = IndexVec::from_elem(0u32, body.basic_blocks());
 
         // we can't use mir.predecessors() here because that counts
@@ -262,7 +262,7 @@
     }
 }
 
-pub fn remove_dead_blocks(body: &mut BodyCache<'_>) {
+pub fn remove_dead_blocks(body: &mut BodyAndCache<'_>) {
     let mut seen = BitSet::new_empty(body.basic_blocks().len());
     for (bb, _) in traversal::preorder(body) {
         seen.insert(bb.index());
@@ -296,7 +296,7 @@
 
 impl<'tcx> MirPass<'tcx> for SimplifyLocals {
     fn run_pass(
-        &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>
+        &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>
     ) {
         trace!("running SimplifyLocals on {:?}", source);
         let locals = {
@@ -367,9 +367,14 @@
                 if let StatementKind::Assign(
                     box (p, Rvalue::Use(Operand::Constant(c)))
                 ) = &stmt.kind {
-                    if !p.is_indirect() {
-                        trace!("skipping store of const value {:?} to {:?}", c, p);
-                        return;
+                    match c.literal.val {
+                        // Keep assignments from unevaluated constants around, since the evaluation
+                        // may report errors, even if the use of the constant is dead code.
+                        ty::ConstKind::Unevaluated(..) => {}
+                        _ => if !p.is_indirect() {
+                            trace!("skipping store of const value {:?} to {:?}", c, p);
+                            return;
+                        },
                     }
                 }
             }
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index c8d0f37..aa3c5b0 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -19,7 +19,7 @@
         Cow::Borrowed(&self.label)
     }
 
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         let param_env = tcx.param_env(src.def_id());
         for block in body.basic_blocks_mut() {
             let terminator = block.terminator_mut();
diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs
index 2235de9..752e852 100644
--- a/src/librustc_mir/transform/simplify_try.rs
+++ b/src/librustc_mir/transform/simplify_try.rs
@@ -33,7 +33,7 @@
 pub struct SimplifyArmIdentity;
 
 impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
-    fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
         for bb in basic_blocks {
             // Need 3 statements:
@@ -151,7 +151,7 @@
 pub struct SimplifyBranchSame;
 
 impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
-    fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         let mut did_remove_blocks = false;
         let bbs = body.basic_blocks_mut();
         for bb_idx in bbs.indices() {
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
deleted file mode 100644
index 3fc76ef..0000000
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ /dev/null
@@ -1,381 +0,0 @@
-// This pass converts move out from array by Subslice and
-// ConstIndex{.., from_end: true} to ConstIndex move out(s) from begin
-// of array. It allows detect error by mir borrowck and elaborate
-// drops for array without additional work.
-//
-// Example:
-//
-// let a = [ box 1,box 2, box 3];
-// if b {
-//  let [_a.., _] = a;
-// } else {
-//  let [.., _b] = a;
-// }
-//
-//  mir statement _10 = move _2[:-1]; replaced by:
-//  StorageLive(_12);
-//  _12 = move _2[0 of 3];
-//  StorageLive(_13);
-//  _13 = move _2[1 of 3];
-//  _10 = [move _12, move _13]
-//  StorageDead(_12);
-//  StorageDead(_13);
-//
-//  and mir statement _11 = move _2[-1 of 1]; replaced by:
-//  _11 = move _2[2 of 3];
-//
-// FIXME: integrate this transformation to the mir build
-
-use rustc::ty;
-use rustc::ty::TyCtxt;
-use rustc::mir::*;
-use rustc::mir::visit::{Visitor, PlaceContext, NonUseContext};
-use rustc_index::vec::{IndexVec};
-use crate::transform::{MirPass, MirSource};
-use crate::util::patch::MirPatch;
-
-pub struct UniformArrayMoveOut;
-
-impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
-        let mut patch = MirPatch::new(body);
-        let param_env = tcx.param_env(src.def_id());
-        {
-            let read_only_cache = read_only!(body);
-            let mut visitor
-                = UniformArrayMoveOutVisitor{ body, patch: &mut patch, tcx, param_env};
-            visitor.visit_body(read_only_cache);
-        }
-        patch.apply(body);
-    }
-}
-
-struct UniformArrayMoveOutVisitor<'a, 'tcx> {
-    body: &'a Body<'tcx>,
-    patch: &'a mut MirPatch<'tcx>,
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
-    fn visit_assign(&mut self,
-                    dst_place: &Place<'tcx>,
-                    rvalue: &Rvalue<'tcx>,
-                    location: Location) {
-        if let Rvalue::Use(Operand::Move(ref src_place)) = rvalue {
-            if let &[ref proj_base @ .., elem] = src_place.projection.as_ref() {
-                if let ProjectionElem::ConstantIndex{offset: _,
-                                                     min_length: _,
-                                                     from_end: false} = elem {
-                    // no need to transformation
-                } else {
-                    let place_ty =
-                        Place::ty_from(&src_place.base, proj_base, self.body, self.tcx).ty;
-                    if let ty::Array(item_ty, const_size) = place_ty.kind {
-                        if let Some(size) = const_size.try_eval_usize(self.tcx, self.param_env) {
-                            assert!(size <= u32::max_value() as u64,
-                                    "uniform array move out doesn't supported
-                                     for array bigger then u32");
-                            self.uniform(
-                                location,
-                                dst_place,
-                                &src_place.base,
-                                &src_place.projection,
-                                item_ty,
-                                size as u32,
-                            );
-                        }
-                    }
-
-                }
-            }
-        }
-        self.super_assign(dst_place, rvalue, location)
-    }
-}
-
-impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
-    fn uniform(&mut self,
-               location: Location,
-               dst_place: &Place<'tcx>,
-               base: &PlaceBase<'tcx>,
-               proj: &[PlaceElem<'tcx>],
-               item_ty: &'tcx ty::TyS<'tcx>,
-               size: u32) {
-        if let [proj_base @ .., elem] = proj {
-            match elem {
-                // uniforms statements like_10 = move _2[:-1];
-                ProjectionElem::Subslice{from, to} => {
-                    self.patch.make_nop(location);
-                    let temps : Vec<_> = (*from..(size-*to)).map(|i| {
-                        let temp =
-                            self.patch.new_temp(item_ty, self.body.source_info(location).span);
-                        self.patch.add_statement(location, StatementKind::StorageLive(temp));
-
-                        let mut projection = proj_base.to_vec();
-                        projection.push(ProjectionElem::ConstantIndex {
-                            offset: i,
-                            min_length: size,
-                            from_end: false,
-                        });
-                        self.patch.add_assign(
-                            location,
-                            Place::from(temp),
-                            Rvalue::Use(Operand::Move(Place {
-                                base: base.clone(),
-                                projection: self.tcx.intern_place_elems(&projection),
-                            })),
-                        );
-                        temp
-                    }).collect();
-                    self.patch.add_assign(
-                        location,
-                        dst_place.clone(),
-                        Rvalue::Aggregate(
-                            box AggregateKind::Array(item_ty),
-                            temps.iter().map(
-                                |x| Operand::Move(Place::from(*x))
-                            ).collect()
-                        )
-                    );
-                    for temp in temps {
-                        self.patch.add_statement(location, StatementKind::StorageDead(temp));
-                    }
-                }
-                // uniforms statements like _11 = move _2[-1 of 1];
-                ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true} => {
-                    self.patch.make_nop(location);
-
-                    let mut projection = proj_base.to_vec();
-                    projection.push(ProjectionElem::ConstantIndex {
-                        offset: size - offset,
-                        min_length: size,
-                        from_end: false,
-                    });
-                    self.patch.add_assign(
-                        location,
-                        dst_place.clone(),
-                        Rvalue::Use(Operand::Move(Place {
-                            base: base.clone(),
-                            projection: self.tcx.intern_place_elems(&projection),
-                        })),
-                    );
-                }
-                _ => {}
-            }
-        }
-    }
-}
-
-// Restore Subslice move out after analysis
-// Example:
-//
-//  next statements:
-//   StorageLive(_12);
-//   _12 = move _2[0 of 3];
-//   StorageLive(_13);
-//   _13 = move _2[1 of 3];
-//   _10 = [move _12, move _13]
-//   StorageDead(_12);
-//   StorageDead(_13);
-//
-// replaced by _10 = move _2[:-1];
-
-pub struct RestoreSubsliceArrayMoveOut<'tcx> {
-    tcx: TyCtxt<'tcx>
-}
-
-impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
-        let mut patch = MirPatch::new(body);
-        let param_env = tcx.param_env(src.def_id());
-        {
-            let read_only_cache = read_only!(body);
-            let mut visitor = RestoreDataCollector {
-                locals_use: IndexVec::from_elem(LocalUse::new(), &body.local_decls),
-                candidates: vec![],
-            };
-            visitor.visit_body(read_only_cache);
-
-            for candidate in &visitor.candidates {
-                let statement = &body[candidate.block].statements[candidate.statement_index];
-                if let StatementKind::Assign(box(ref dst_place, ref rval)) = statement.kind {
-                    if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = *rval {
-                        let items : Vec<_> = items.iter().map(|item| {
-                            if let Operand::Move(place) = item {
-                                if let Some(local) = place.as_local() {
-                                    let local_use = &visitor.locals_use[local];
-                                    let opt_index_and_place =
-                                        Self::try_get_item_source(local_use, body);
-                                    // each local should be used twice:
-                                    //  in assign and in aggregate statements
-                                    if local_use.use_count == 2 && opt_index_and_place.is_some() {
-                                        let (index, src_place) = opt_index_and_place.unwrap();
-                                        return Some((local_use, index, src_place));
-                                    }
-                                }
-                            }
-                            None
-                        }).collect();
-
-                        let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
-                        let opt_size = opt_src_place.and_then(|src_place| {
-                            let src_ty = Place::ty_from(
-                                src_place.base,
-                                src_place.projection,
-                                &**body,
-                                tcx
-                            ).ty;
-                            if let ty::Array(_, ref size_o) = src_ty.kind {
-                                size_o.try_eval_usize(tcx, param_env)
-                            } else {
-                                None
-                            }
-                        });
-                        let restore_subslice = RestoreSubsliceArrayMoveOut { tcx };
-                        restore_subslice
-                            .check_and_patch(*candidate, &items, opt_size, &mut patch, dst_place);
-                    }
-                }
-            }
-        }
-        patch.apply(body);
-    }
-}
-
-impl RestoreSubsliceArrayMoveOut<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
-        RestoreSubsliceArrayMoveOut { tcx }
-    }
-
-    // Checks that source has size, all locals are inited from same source place and
-    // indices is an integer interval. If all checks pass do the replacent.
-    // items are Vec<Option<LocalUse, index in source array, source place for init local>>
-    fn check_and_patch(&self,
-                       candidate: Location,
-                       items: &[Option<(&LocalUse, u32, PlaceRef<'_, 'tcx>)>],
-                       opt_size: Option<u64>,
-                       patch: &mut MirPatch<'tcx>,
-                       dst_place: &Place<'tcx>) {
-        let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
-
-        if opt_size.is_some() && items.iter().all(
-            |l| l.is_some() && l.unwrap().2 == opt_src_place.unwrap()) {
-            let src_place = opt_src_place.unwrap();
-
-            let indices: Vec<_> = items.iter().map(|x| x.unwrap().1).collect();
-            for i in 1..indices.len() {
-                if indices[i - 1] + 1 != indices[i] {
-                    return;
-                }
-            }
-
-            let min = *indices.first().unwrap();
-            let max = *indices.last().unwrap();
-
-            for item in items {
-                let locals_use = item.unwrap().0;
-                patch.make_nop(locals_use.alive.unwrap());
-                patch.make_nop(locals_use.dead.unwrap());
-                patch.make_nop(locals_use.first_use.unwrap());
-            }
-            patch.make_nop(candidate);
-            let size = opt_size.unwrap() as u32;
-
-            let mut projection = src_place.projection.to_vec();
-            projection.push(ProjectionElem::Subslice { from: min, to: size - max - 1 });
-            patch.add_assign(
-                candidate,
-                dst_place.clone(),
-                Rvalue::Use(Operand::Move(Place {
-                    base: src_place.base.clone(),
-                    projection: self.tcx.intern_place_elems(&projection),
-                })),
-            );
-        }
-    }
-
-    fn try_get_item_source<'a>(local_use: &LocalUse,
-                               body: &'a Body<'tcx>) -> Option<(u32, PlaceRef<'a, 'tcx>)> {
-        if let Some(location) = local_use.first_use {
-            let block = &body[location.block];
-            if block.statements.len() > location.statement_index {
-                let statement = &block.statements[location.statement_index];
-                if let StatementKind::Assign(
-                    box(place, Rvalue::Use(Operand::Move(src_place)))
-                ) = &statement.kind {
-                    if let (Some(_), PlaceRef {
-                        base: _,
-                        projection: &[.., ProjectionElem::ConstantIndex {
-                            offset, min_length: _, from_end: false
-                        }],
-                    }) = (place.as_local(), src_place.as_ref()) {
-                        if let StatementKind::Assign(
-                            box(_, Rvalue::Use(Operand::Move(place)))
-                        ) = &statement.kind {
-                            if let PlaceRef {
-                                base,
-                                projection: &[ref proj_base @ .., _],
-                            } = place.as_ref() {
-                                return Some((offset, PlaceRef {
-                                    base,
-                                    projection: proj_base,
-                                }))
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        None
-    }
-}
-
-#[derive(Copy, Clone, Debug)]
-struct LocalUse {
-    alive: Option<Location>,
-    dead: Option<Location>,
-    use_count: u32,
-    first_use: Option<Location>,
-}
-
-impl LocalUse {
-    pub fn new() -> Self {
-        LocalUse{alive: None, dead: None, use_count: 0, first_use: None}
-    }
-}
-
-struct RestoreDataCollector {
-    locals_use: IndexVec<Local, LocalUse>,
-    candidates: Vec<Location>,
-}
-
-impl<'tcx> Visitor<'tcx> for RestoreDataCollector {
-    fn visit_assign(&mut self,
-                    place: &Place<'tcx>,
-                    rvalue: &Rvalue<'tcx>,
-                    location: Location) {
-        if let Rvalue::Aggregate(box AggregateKind::Array(_), _) = *rvalue {
-            self.candidates.push(location);
-        }
-        self.super_assign(place, rvalue, location)
-    }
-
-    fn visit_local(&mut self,
-                   local: &Local,
-                   context: PlaceContext,
-                   location: Location) {
-        let local_use = &mut self.locals_use[*local];
-        match context {
-            PlaceContext::NonUse(NonUseContext::StorageLive) => local_use.alive = Some(location),
-            PlaceContext::NonUse(NonUseContext::StorageDead) => local_use.dead = Some(location),
-            PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {}
-            _ => {
-                local_use.use_count += 1;
-                if local_use.first_use.is_none() {
-                    local_use.first_use = Some(location);
-                }
-            }
-        }
-    }
-}
diff --git a/src/librustc_mir/transform/uninhabited_enum_branching.rs b/src/librustc_mir/transform/uninhabited_enum_branching.rs
index de070d7..0bf0ff2 100644
--- a/src/librustc_mir/transform/uninhabited_enum_branching.rs
+++ b/src/librustc_mir/transform/uninhabited_enum_branching.rs
@@ -2,7 +2,7 @@
 
 use crate::transform::{MirPass, MirSource};
 use rustc::mir::{
-    BasicBlock, BasicBlockData, Body, BodyCache, Local, Operand, Rvalue, StatementKind,
+    BasicBlock, BasicBlockData, Body, BodyAndCache, Local, Operand, Rvalue, StatementKind,
     TerminatorKind,
 };
 use rustc::ty::layout::{Abi, TyLayout, Variants};
@@ -29,7 +29,7 @@
     // Only bother checking blocks which terminate by switching on a local.
     if let Some(local) = get_discriminant_local(&terminator.kind) {
         let stmt_before_term = (block_data.statements.len() > 0)
-            .then_with(|| &block_data.statements[block_data.statements.len() - 1].kind);
+            .then(|| &block_data.statements[block_data.statements.len() - 1].kind);
 
         if let Some(StatementKind::Assign(box (l, Rvalue::Discriminant(place)))) = stmt_before_term
         {
@@ -59,14 +59,14 @@
             .iter_enumerated()
             .filter_map(|(idx, layout)| {
                 (layout.abi != Abi::Uninhabited)
-                    .then_with(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
+                    .then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
             })
             .collect(),
     }
 }
 
 impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
         if source.promoted.is_some() {
             return;
         }
diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs
index f94bea2..4006787 100644
--- a/src/librustc_mir/util/collect_writes.rs
+++ b/src/librustc_mir/util/collect_writes.rs
@@ -1,5 +1,5 @@
 use rustc::mir::{Local, Location};
-use rustc::mir::ReadOnlyBodyCache;
+use rustc::mir::ReadOnlyBodyAndCache;
 use rustc::mir::visit::PlaceContext;
 use rustc::mir::visit::Visitor;
 
@@ -9,7 +9,7 @@
     fn find_assignments(&self, local: Local) -> Vec<Location>;
 }
 
-impl<'a, 'tcx> FindAssignments for ReadOnlyBodyCache<'a, 'tcx>{
+impl<'a, 'tcx> FindAssignments for ReadOnlyBodyAndCache<'a, 'tcx>{
     fn find_assignments(&self, local: Local) -> Vec<Location>{
             let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]};
             visitor.visit_body(*self);
diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs
index 1907e9b..cf98755 100644
--- a/src/librustc_mir/util/def_use.rs
+++ b/src/librustc_mir/util/def_use.rs
@@ -1,6 +1,8 @@
 //! Def-use analysis.
 
-use rustc::mir::{Body, BodyCache, Local, Location, PlaceElem, ReadOnlyBodyCache, VarDebugInfo};
+use rustc::mir::{
+    Body, BodyAndCache, Local, Location, PlaceElem, ReadOnlyBodyAndCache, VarDebugInfo,
+};
 use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
 use rustc::ty::TyCtxt;
 use rustc_index::vec::IndexVec;
@@ -30,7 +32,7 @@
         }
     }
 
-    pub fn analyze(&mut self, body: ReadOnlyBodyCache<'_, '_>) {
+    pub fn analyze(&mut self, body: ReadOnlyBodyAndCache<'_, '_>) {
         self.clear();
 
         let mut finder = DefUseFinder {
@@ -55,7 +57,7 @@
     fn mutate_defs_and_uses(
         &self,
         local: Local,
-        body: &mut BodyCache<'tcx>,
+        body: &mut BodyAndCache<'tcx>,
         new_local: Local,
         tcx: TyCtxt<'tcx>,
     ) {
@@ -73,7 +75,7 @@
     // FIXME(pcwalton): this should update the def-use chains.
     pub fn replace_all_defs_and_uses_with(&self,
                                           local: Local,
-                                          body: &mut BodyCache<'tcx>,
+                                          body: &mut BodyAndCache<'tcx>,
                                           new_local: Local,
                                           tcx: TyCtxt<'tcx>) {
         self.mutate_defs_and_uses(local, body, new_local, tcx)
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index 3a7ec9f..a44d401 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -202,7 +202,7 @@
     }
 
     for var_debug_info in &body.var_debug_info {
-        write!(w, r#"debug {} => {};<br align="left"/>"#,
+        write!(w, r#"debug {} =&gt; {};<br align="left"/>"#,
                var_debug_info.name, escape(&var_debug_info.place))?;
     }
 
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 3349753..68c2e16 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -57,7 +57,7 @@
 /// Computes which local variables are live within the given function
 /// `mir`, including drops.
 pub fn liveness_of_locals(
-    body: ReadOnlyBodyCache<'_, '_>,
+    body: ReadOnlyBodyAndCache<'_, '_>,
 ) -> LivenessResult {
     let num_live_vars = body.local_decls.len();
 
diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs
index 47bb0b6..575b6d2 100644
--- a/src/librustc_mir/util/patch.rs
+++ b/src/librustc_mir/util/patch.rs
@@ -127,7 +127,7 @@
         self.make_nop.push(loc);
     }
 
-    pub fn apply(self, body: &mut BodyCache<'tcx>) {
+    pub fn apply(self, body: &mut BodyAndCache<'tcx>) {
         debug!("MirPatch: make nops at: {:?}", self.make_nop);
         for loc in self.make_nop {
             body.make_statement_nop(loc);
diff --git a/src/librustc_parse/Cargo.toml b/src/librustc_parse/Cargo.toml
index 95b3256..fb5cb74 100644
--- a/src/librustc_parse/Cargo.toml
+++ b/src/librustc_parse/Cargo.toml
@@ -12,12 +12,11 @@
 [dependencies]
 bitflags = "1.0"
 log = "0.4"
-syntax_pos = { path = "../libsyntax_pos" }
-syntax = { path = "../libsyntax" }
-errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_lexer = { path = "../librustc_lexer" }
-rustc_target = { path = "../librustc_target" }
-smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+rustc_errors = { path = "../librustc_errors" }
 rustc_error_codes = { path = "../librustc_error_codes" }
+smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+syntax_pos = { path = "../libsyntax_pos" }
+syntax = { path = "../libsyntax" }
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
index 1bf6e9e..1e9203f 100644
--- a/src/librustc_parse/config.rs
+++ b/src/librustc_parse/config.rs
@@ -8,20 +8,21 @@
 //!
 //! [#64197]: https://github.com/rust-lang/rust/issues/64197
 
-use crate::validate_attr;
+use crate::{parse_in, validate_attr};
 use rustc_feature::Features;
+use rustc_errors::Applicability;
 use syntax::attr::HasAttrs;
 use syntax::feature_gate::{feature_err, get_features};
 use syntax::attr;
-use syntax::ast;
+use syntax::ast::{self, Attribute, AttrItem, MetaItem};
 use syntax::edition::Edition;
 use syntax::mut_visit::*;
 use syntax::ptr::P;
 use syntax::sess::ParseSess;
 use syntax::util::map_in_place::MapInPlace;
+use syntax_pos::Span;
 use syntax_pos::symbol::sym;
 
-use errors::Applicability;
 use smallvec::SmallVec;
 
 /// A folder that strips out items that do not belong in the current configuration.
@@ -72,10 +73,15 @@
     }
 }
 
+const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
+const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
+    <https://doc.rust-lang.org/reference/conditional-compilation.html\
+    #the-cfg_attr-attribute>";
+
 impl<'a> StripUnconfigured<'a> {
     pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
         self.process_cfg_attrs(&mut node);
-        if self.in_cfg(node.attrs()) { Some(node) } else { None }
+        self.in_cfg(node.attrs()).then_some(node)
     }
 
     /// Parse and expand all `cfg_attr` attributes into a list of attributes
@@ -97,34 +103,14 @@
     /// Gives a compiler warning when the `cfg_attr` contains no attributes and
     /// is in the original source file. Gives a compiler error if the syntax of
     /// the attribute is incorrect.
-    fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
+    fn process_cfg_attr(&mut self, attr: Attribute) -> Vec<Attribute> {
         if !attr.has_name(sym::cfg_attr) {
             return vec![attr];
         }
-        if let ast::MacArgs::Empty = attr.get_normal_item().args {
-            self.sess.span_diagnostic
-                .struct_span_err(
-                    attr.span,
-                    "malformed `cfg_attr` attribute input",
-                ).span_suggestion(
-                    attr.span,
-                    "missing condition and attribute",
-                    "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(),
-                    Applicability::HasPlaceholders,
-                ).note("for more information, visit \
-                       <https://doc.rust-lang.org/reference/conditional-compilation.html\
-                       #the-cfg_attr-attribute>")
-                .emit();
-            return vec![];
-        }
 
-        let res = crate::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr());
-        let (cfg_predicate, expanded_attrs) = match res {
-            Ok(result) => result,
-            Err(mut e) => {
-                e.emit();
-                return vec![];
-            }
+        let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) {
+            None => return vec![],
+            Some(r) => r,
         };
 
         // Lint on zero attributes in source.
@@ -135,24 +121,56 @@
         // At this point we know the attribute is considered used.
         attr::mark_used(&attr);
 
-        if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
-            // We call `process_cfg_attr` recursively in case there's a
-            // `cfg_attr` inside of another `cfg_attr`. E.g.
-            //  `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
-            expanded_attrs.into_iter()
-            .flat_map(|(item, span)| self.process_cfg_attr(attr::mk_attr_from_item(
-                attr.style,
-                item,
-                span,
-            )))
-            .collect()
-        } else {
-            vec![]
+        if !attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
+            return vec![];
         }
+
+        // We call `process_cfg_attr` recursively in case there's a
+        // `cfg_attr` inside of another `cfg_attr`. E.g.
+        //  `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
+        expanded_attrs
+            .into_iter()
+            .flat_map(|(item, span)| {
+                let attr = attr::mk_attr_from_item(attr.style, item, span);
+                self.process_cfg_attr(attr)
+            })
+            .collect()
+    }
+
+    fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
+        match attr.get_normal_item().args {
+            ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
+                let msg = "wrong `cfg_attr` delimiters";
+                validate_attr::check_meta_bad_delim(self.sess, dspan, delim, msg);
+                match parse_in(self.sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
+                    Ok(r) => return Some(r),
+                    Err(mut e) => e
+                        .help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
+                        .note(CFG_ATTR_NOTE_REF)
+                        .emit(),
+                }
+            }
+            _ => self.error_malformed_cfg_attr_missing(attr.span),
+        }
+        None
+    }
+
+    fn error_malformed_cfg_attr_missing(&self, span: Span) {
+        self.sess
+            .span_diagnostic
+            .struct_span_err(span, "malformed `cfg_attr` attribute input")
+            .span_suggestion(
+                span,
+                "missing condition and attribute",
+                CFG_ATTR_GRAMMAR_HELP.to_string(),
+                Applicability::HasPlaceholders,
+            )
+            .note(CFG_ATTR_NOTE_REF)
+            .emit();
     }
 
     /// Determines if a node with the given attributes should be included in this configuration.
-    pub fn in_cfg(&self, attrs: &[ast::Attribute]) -> bool {
+    pub fn in_cfg(&self, attrs: &[Attribute]) -> bool {
         attrs.iter().all(|attr| {
             if !is_cfg(attr) {
                 return true;
@@ -199,7 +217,7 @@
     }
 
     /// Visit attributes on expression and statements (but not attributes on items in blocks).
-    fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
+    fn visit_expr_attrs(&mut self, attrs: &[Attribute]) {
         // flag the offending attributes
         for attr in attrs.iter() {
             self.maybe_emit_expr_attr_err(attr);
@@ -207,7 +225,7 @@
     }
 
     /// If attributes are not allowed on expressions, emit an error for `attr`
-    pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) {
+    pub fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
         if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
             let mut err = feature_err(self.sess,
                                       sym::stmt_expr_attributes,
@@ -350,7 +368,7 @@
     }
 }
 
-fn is_cfg(attr: &ast::Attribute) -> bool {
+fn is_cfg(attr: &Attribute) -> bool {
     attr.check_name(sym::cfg)
 }
 
@@ -359,8 +377,8 @@
 pub fn process_configure_mod(
     sess: &ParseSess,
     cfg_mods: bool,
-    attrs: &[ast::Attribute],
-) -> (bool, Vec<ast::Attribute>) {
+    attrs: &[Attribute],
+) -> (bool, Vec<Attribute>) {
     // Don't perform gated feature checking.
     let mut strip_unconfigured = StripUnconfigured { sess, features: None };
     let mut attrs = attrs.to_owned();
diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs
index 5de63cb..ddcfea1 100644
--- a/src/librustc_parse/lexer/mod.rs
+++ b/src/librustc_parse/lexer/mod.rs
@@ -1,16 +1,15 @@
-use syntax::token::{self, Token, TokenKind};
-use syntax::sess::ParseSess;
-use syntax::symbol::{sym, Symbol};
-use syntax::util::comments;
-
-use errors::{FatalError, DiagnosticBuilder};
-use syntax_pos::{BytePos, Pos, Span};
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{FatalError, DiagnosticBuilder};
 use rustc_lexer::Base;
 use rustc_lexer::unescape;
+use syntax::token::{self, Token, TokenKind};
+use syntax::sess::ParseSess;
+use syntax::util::comments;
+use syntax_pos::symbol::{sym, Symbol};
+use syntax_pos::{BytePos, Pos, Span};
 
 use std::char;
 use std::convert::TryInto;
-use rustc_data_structures::sync::Lrc;
 use log::debug;
 
 mod tokentrees;
diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs
index 1353591..5791c63 100644
--- a/src/librustc_parse/lexer/tokentrees.rs
+++ b/src/librustc_parse/lexer/tokentrees.rs
@@ -1,13 +1,11 @@
-use rustc_data_structures::fx::FxHashMap;
-use syntax_pos::Span;
-
 use super::{StringReader, UnmatchedBrace};
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::PResult;
 use syntax::print::pprust::token_to_string;
 use syntax::token::{self, Token};
 use syntax::tokenstream::{DelimSpan, IsJoint::{self, *}, TokenStream, TokenTree, TreeAndJoint};
-
-use errors::PResult;
+use syntax_pos::Span;
 
 impl<'a> StringReader<'a> {
     crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
diff --git a/src/librustc_parse/lexer/unicode_chars.rs b/src/librustc_parse/lexer/unicode_chars.rs
index 6eb995b..edfebc7 100644
--- a/src/librustc_parse/lexer/unicode_chars.rs
+++ b/src/librustc_parse/lexer/unicode_chars.rs
@@ -2,9 +2,9 @@
 // http://www.unicode.org/Public/security/10.0.0/confusables.txt
 
 use super::StringReader;
-use errors::{Applicability, DiagnosticBuilder};
-use syntax_pos::{BytePos, Pos, Span, symbol::kw};
 use crate::token;
+use rustc_errors::{Applicability, DiagnosticBuilder};
+use syntax_pos::{BytePos, Pos, Span, symbol::kw};
 
 #[rustfmt::skip] // for line breaks
 const UNICODE_ARRAY: &[(char, &str, char)] = &[
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index a22b383..faff386 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -1,5 +1,6 @@
 //! The main parser interface.
 
+#![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 
 use syntax::ast;
@@ -8,7 +9,7 @@
 use syntax::token::{self, Nonterminal};
 use syntax::tokenstream::{self, TokenStream, TokenTree};
 
-use errors::{PResult, FatalError, Level, Diagnostic};
+use rustc_errors::{PResult, FatalError, Level, Diagnostic};
 use rustc_data_structures::sync::Lrc;
 use syntax_pos::{Span, SourceFile, FileName};
 
@@ -53,7 +54,7 @@
 macro_rules! panictry_buffer {
     ($handler:expr, $e:expr) => ({
         use std::result::Result::{Ok, Err};
-        use errors::FatalError;
+        use rustc_errors::FatalError;
         match $e {
             Ok(e) => e,
             Err(errs) => {
@@ -270,21 +271,13 @@
 }
 
 /// Runs the given subparser `f` on the tokens of the given `attr`'s item.
-pub fn parse_in_attr<'a, T>(
+pub fn parse_in<'a, T>(
     sess: &'a ParseSess,
-    attr: &ast::Attribute,
+    tts: TokenStream,
+    name: &'static str,
     mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
 ) -> PResult<'a, T> {
-    let mut parser = Parser::new(
-        sess,
-        // FIXME(#66940, Centril | petrochenkov): refactor this function so it doesn't
-        // require reconstructing and immediately re-parsing delimiters.
-        attr.get_normal_item().args.outer_tokens(),
-        None,
-        false,
-        false,
-        Some("attribute"),
-    );
+    let mut parser = Parser::new(sess, tts, None, false, false, Some(name));
     let result = f(&mut parser)?;
     if parser.token != token::Eof {
         parser.unexpected()?;
diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs
index c726140..00fd6b8 100644
--- a/src/librustc_parse/parser/attr.rs
+++ b/src/librustc_parse/parser/attr.rs
@@ -1,10 +1,10 @@
 use super::{SeqSep, Parser, TokenType, PathStyle};
+use rustc_errors::PResult;
 use syntax::attr;
 use syntax::ast;
 use syntax::util::comments;
 use syntax::token::{self, Nonterminal};
 use syntax_pos::{Span, Symbol};
-use errors::PResult;
 
 use log::debug;
 
@@ -220,7 +220,7 @@
         Ok(attrs)
     }
 
-    pub(super) fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
+    crate fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
         let lit = self.parse_lit()?;
         debug!("checking if {:?} is unusuffixed", lit);
 
@@ -238,25 +238,36 @@
 
     /// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
     pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> {
-        self.expect(&token::OpenDelim(token::Paren))?;
-
         let cfg_predicate = self.parse_meta_item()?;
         self.expect(&token::Comma)?;
 
         // Presumably, the majority of the time there will only be one attr.
         let mut expanded_attrs = Vec::with_capacity(1);
-
-        while !self.check(&token::CloseDelim(token::Paren)) {
-            let lo = self.token.span.lo();
+        while self.token.kind != token::Eof {
+            let lo = self.token.span;
             let item = self.parse_attr_item()?;
-            expanded_attrs.push((item, self.prev_span.with_lo(lo)));
-            self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?;
+            expanded_attrs.push((item, lo.to(self.prev_span)));
+            if !self.eat(&token::Comma) {
+                break;
+            }
         }
 
-        self.expect(&token::CloseDelim(token::Paren))?;
         Ok((cfg_predicate, expanded_attrs))
     }
 
+    /// Matches `COMMASEP(meta_item_inner)`.
+    crate fn parse_meta_seq_top(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
+        // Presumably, the majority of the time there will only be one attr.
+        let mut nmis = Vec::with_capacity(1);
+        while self.token.kind != token::Eof {
+            nmis.push(self.parse_meta_item_inner()?);
+            if !self.eat(&token::Comma) {
+                break;
+            }
+        }
+        Ok(nmis)
+    }
+
     /// Matches the following grammar (per RFC 1559).
     ///
     ///     meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index da8bf89..ba125ca 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -1,25 +1,22 @@
 use super::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType, SeqSep, Parser};
 
-use syntax::ast::{
-    self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind,
-    Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
-};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{self, PResult, Applicability, DiagnosticBuilder, Handler, pluralize};
+use rustc_error_codes::*;
+use syntax::ast::{self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item};
+use syntax::ast::{ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind};
 use syntax::token::{self, TokenKind, token_can_begin_expr};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::symbol::{kw, sym};
 use syntax::ThinVec;
 use syntax::util::parser::AssocOp;
 use syntax::struct_span_err;
-
-use errors::{PResult, Applicability, DiagnosticBuilder, pluralize};
-use rustc_data_structures::fx::FxHashSet;
+use syntax_pos::symbol::{kw, sym};
 use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError};
+
 use log::{debug, trace};
 use std::mem;
 
-use rustc_error_codes::*;
-
 const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify type arguments";
 
 /// Creates a placeholder argument.
@@ -61,10 +58,10 @@
 }
 
 impl Error {
-    fn span_err<S: Into<MultiSpan>>(
+    fn span_err(
         self,
-        sp: S,
-        handler: &errors::Handler,
+        sp: impl Into<MultiSpan>,
+        handler: &Handler,
     ) -> DiagnosticBuilder<'_> {
         match self {
             Error::FileNotFoundForModule {
@@ -212,7 +209,7 @@
         self.sess.span_diagnostic.span_bug(sp, m)
     }
 
-    pub(super) fn diagnostic(&self) -> &'a errors::Handler {
+    pub(super) fn diagnostic(&self) -> &'a Handler {
         &self.sess.span_diagnostic
     }
 
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 1112274..3cd4988 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -4,23 +4,20 @@
 use super::diagnostics::Error;
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
-use syntax::ast::{
-    self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode,
-    Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind,
-    FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, Lit,
-};
+use rustc_data_structures::thin_vec::ThinVec;
+use rustc_errors::{PResult, Applicability};
+use syntax::ast::{self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode};
+use syntax::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind};
+use syntax::ast::{FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, Lit};
 use syntax::token::{self, Token, TokenKind};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::source_map::{self, Span};
 use syntax::util::classify;
 use syntax::util::literal::LitError;
 use syntax::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
-use syntax_pos::symbol::{kw, sym};
-use syntax_pos::Symbol;
-use errors::{PResult, Applicability};
+use syntax_pos::source_map::{self, Span};
+use syntax_pos::symbol::{kw, sym, Symbol};
 use std::mem;
-use rustc_data_structures::thin_vec::ThinVec;
 
 /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
 /// dropped into the token stream, which happens while parsing the result of
diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs
index ba5eafc..32819cc 100644
--- a/src/librustc_parse/parser/generics.rs
+++ b/src/librustc_parse/parser/generics.rs
@@ -1,11 +1,11 @@
 use super::Parser;
 
+use rustc_errors::PResult;
 use syntax::ast::{self, WhereClause, GenericParam, GenericParamKind, GenericBounds, Attribute};
 use syntax::token;
 use syntax::source_map::DUMMY_SP;
 use syntax_pos::symbol::{kw, sym};
 
-use errors::PResult;
 
 impl<'a> Parser<'a> {
     /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 66a1352..34ef12e 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -3,6 +3,8 @@
 
 use crate::maybe_whole;
 
+use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey};
+use rustc_error_codes::*;
 use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
 use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
 use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
@@ -14,16 +16,13 @@
 use syntax::ThinVec;
 use syntax::token;
 use syntax::tokenstream::{DelimSpan, TokenTree, TokenStream};
-use syntax::source_map::{self, respan, Span};
 use syntax::struct_span_err;
 use syntax_pos::BytePos;
+use syntax_pos::source_map::{self, respan, Span};
 use syntax_pos::symbol::{kw, sym, Symbol};
 
-use rustc_error_codes::*;
-
 use log::debug;
 use std::mem;
-use errors::{PResult, Applicability, DiagnosticBuilder, StashKey};
 
 pub(super) type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>);
 
@@ -1182,6 +1181,7 @@
                         attrs,
                         vis: visibility,
                         kind: ForeignItemKind::Macro(mac),
+                        tokens: None,
                     }
                 )
             }
@@ -1212,6 +1212,7 @@
             id: DUMMY_NODE_ID,
             span: lo.to(hi),
             vis,
+            tokens: None,
         })
     }
 
@@ -1229,7 +1230,8 @@
             kind: ForeignItemKind::Ty,
             id: DUMMY_NODE_ID,
             span: lo.to(hi),
-            vis
+            vis,
+            tokens: None,
         })
     }
 
@@ -1728,9 +1730,10 @@
     /// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case
     /// it is, we try to parse the item and report error about nested types.
     fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
-        if self.token.is_keyword(kw::Enum) ||
+        if (self.token.is_keyword(kw::Enum) ||
             self.token.is_keyword(kw::Struct) ||
-            self.token.is_keyword(kw::Union)
+            self.token.is_keyword(kw::Union))
+           && self.look_ahead(1, |t| t.is_ident())
         {
             let kw_token = self.token.clone();
             let kw_str = pprust::token_to_string(&kw_token);
@@ -1826,6 +1829,7 @@
             id: DUMMY_NODE_ID,
             span,
             vis,
+            tokens: None,
         })
     }
 
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index 2868972..07e99cf 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -14,23 +14,20 @@
 use crate::{Directory, DirectoryOwnership};
 use crate::lexer::UnmatchedBrace;
 
-use syntax::ast::{
-    self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit,
-    IsAsync, MacArgs, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety,
-};
-
+use rustc_errors::{PResult, Applicability, DiagnosticBuilder, FatalError};
+use rustc_data_structures::thin_vec::ThinVec;
+use syntax::ast::{self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit};
+use syntax::ast::{IsAsync, MacArgs, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety};
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::token::{self, Token, TokenKind, DelimToken};
 use syntax::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
 use syntax::sess::ParseSess;
-use syntax::source_map::respan;
 use syntax::struct_span_err;
 use syntax::util::comments::{doc_comment_style, strip_doc_comment_decoration};
+use syntax_pos::source_map::respan;
 use syntax_pos::symbol::{kw, sym, Symbol};
 use syntax_pos::{Span, BytePos, DUMMY_SP, FileName};
-use rustc_data_structures::thin_vec::ThinVec;
-use errors::{PResult, Applicability, DiagnosticBuilder, FatalError};
 use log::debug;
 
 use std::borrow::Cow;
diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs
index 59d7c2b..3777e17 100644
--- a/src/librustc_parse/parser/module.rs
+++ b/src/librustc_parse/parser/module.rs
@@ -4,13 +4,12 @@
 
 use crate::{new_sub_parser_from_file, DirectoryOwnership};
 
+use rustc_errors::PResult;
 use syntax::attr;
 use syntax::ast::{self, Ident, Attribute, ItemKind, Mod, Crate};
 use syntax::token::{self, TokenKind};
-use syntax::source_map::{SourceMap, Span, DUMMY_SP, FileName};
-
+use syntax_pos::source_map::{SourceMap, Span, DUMMY_SP, FileName};
 use syntax_pos::symbol::sym;
-use errors::PResult;
 
 use std::path::{self, Path, PathBuf};
 
@@ -212,13 +211,13 @@
         // `./<id>.rs` and `./<id>/mod.rs`.
         let relative_prefix_string;
         let relative_prefix = if let Some(ident) = relative {
-            relative_prefix_string = format!("{}{}", ident, path::MAIN_SEPARATOR);
+            relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR);
             &relative_prefix_string
         } else {
             ""
         };
 
-        let mod_name = id.to_string();
+        let mod_name = id.name.to_string();
         let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
         let secondary_path_str = format!("{}{}{}mod.rs",
                                          relative_prefix, mod_name, path::MAIN_SEPARATOR);
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index 1127c4b..117b92d 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -1,5 +1,6 @@
 use super::{Parser, PathStyle};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
+use rustc_errors::{PResult, Applicability, DiagnosticBuilder};
 use syntax::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac};
 use syntax::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind};
 use syntax::mut_visit::{noop_visit_pat, noop_visit_mac, MutVisitor};
@@ -7,9 +8,8 @@
 use syntax::print::pprust;
 use syntax::ThinVec;
 use syntax::token;
-use syntax::source_map::{respan, Span, Spanned};
+use syntax_pos::source_map::{respan, Span, Spanned};
 use syntax_pos::symbol::{kw, sym};
-use errors::{PResult, Applicability, DiagnosticBuilder};
 
 type Expected = Option<&'static str>;
 
@@ -459,18 +459,28 @@
     /// Parse `&pat` / `&mut pat`.
     fn parse_pat_deref(&mut self, expected: Expected) -> PResult<'a, PatKind> {
         self.expect_and()?;
+        self.recover_lifetime_in_deref_pat();
         let mutbl = self.parse_mutability();
-
-        if let token::Lifetime(name) = self.token.kind {
-            let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name));
-            err.span_label(self.token.span, "unexpected lifetime");
-            return Err(err);
-        }
-
         let subpat = self.parse_pat_with_range_pat(false, expected)?;
         Ok(PatKind::Ref(subpat, mutbl))
     }
 
+    fn recover_lifetime_in_deref_pat(&mut self) {
+        if let token::Lifetime(name) = self.token.kind {
+            self.bump(); // `'a`
+
+            let span = self.prev_span;
+            self.struct_span_err(span, &format!("unexpected lifetime `{}` in pattern", name))
+                .span_suggestion(
+                    span,
+                    "remove the lifetime",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+        }
+    }
+
     /// Parse a tuple or parenthesis pattern.
     fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
         let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?;
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index 75bb67d..5334fc4 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -1,16 +1,15 @@
 use super::{Parser, TokenType};
 use crate::maybe_whole;
+use rustc_errors::{PResult, Applicability, pluralize};
 use syntax::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, AngleBracketedArgs};
 use syntax::ast::{AnonConst, GenericArg, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
-use syntax::ast::MacArgs;
 use syntax::ThinVec;
 use syntax::token::{self, Token};
-use syntax::source_map::{Span, BytePos};
+use syntax_pos::source_map::{Span, BytePos};
 use syntax_pos::symbol::{kw, sym};
 
 use std::mem;
 use log::debug;
-use errors::{PResult, Applicability, pluralize};
 
 /// Specifies how to parse a path.
 #[derive(Copy, Clone, PartialEq)]
@@ -109,42 +108,6 @@
         Ok(Path { segments, span: lo.to(self.prev_span) })
     }
 
-    /// Like `parse_path`, but also supports parsing `Word` meta items into paths for
-    /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]`
-    /// attributes.
-    fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> {
-        let meta_ident = match self.token.kind {
-            token::Interpolated(ref nt) => match **nt {
-                token::NtMeta(ref item) => match item.args {
-                    MacArgs::Empty => Some(item.path.clone()),
-                    _ => None,
-                },
-                _ => None,
-            },
-            _ => None,
-        };
-        if let Some(path) = meta_ident {
-            self.bump();
-            return Ok(path);
-        }
-        self.parse_path(style)
-    }
-
-    /// Parse a list of paths inside `#[derive(path_0, ..., path_n)]`.
-    pub fn parse_derive_paths(&mut self) -> PResult<'a, Vec<Path>> {
-        self.expect(&token::OpenDelim(token::Paren))?;
-        let mut list = Vec::new();
-        while !self.eat(&token::CloseDelim(token::Paren)) {
-            let path = self.parse_path_allowing_meta(PathStyle::Mod)?;
-            list.push(path);
-            if !self.eat(&token::Comma) {
-                self.expect(&token::CloseDelim(token::Paren))?;
-                break
-            }
-        }
-        Ok(list)
-    }
-
     pub(super) fn parse_path_segments(
         &mut self,
         segments: &mut Vec<PathSegment>,
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index b952e88..943b6ec 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -6,6 +6,7 @@
 use crate::maybe_whole;
 use crate::DirectoryOwnership;
 
+use rustc_errors::{PResult, Applicability};
 use syntax::ThinVec;
 use syntax::ptr::P;
 use syntax::ast;
@@ -13,11 +14,10 @@
 use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac};
 use syntax::util::classify;
 use syntax::token;
-use syntax::source_map::{respan, Span};
-use syntax::symbol::{kw, sym};
+use syntax_pos::source_map::{respan, Span};
+use syntax_pos::symbol::{kw, sym};
 
 use std::mem;
-use errors::{PResult, Applicability};
 
 impl<'a> Parser<'a> {
     /// Parses a statement. This stops just before trailing semicolons on everything but items.
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 3214279..84ffef6 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -3,19 +3,17 @@
 
 use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath};
 
+use rustc_errors::{PResult, Applicability, pluralize};
+use rustc_error_codes::*;
 use syntax::ptr::P;
 use syntax::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident};
 use syntax::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
 use syntax::ast::{Mutability, AnonConst, Mac};
 use syntax::token::{self, Token};
-use syntax::source_map::Span;
 use syntax::struct_span_fatal;
+use syntax_pos::source_map::Span;
 use syntax_pos::symbol::kw;
 
-use errors::{PResult, Applicability, pluralize};
-
-use rustc_error_codes::*;
-
 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
 /// `IDENT<<u8 as Trait>::AssocTy>`.
 ///
diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs
index 8601add..94d3fe7 100644
--- a/src/librustc_parse/validate_attr.rs
+++ b/src/librustc_parse/validate_attr.rs
@@ -1,10 +1,13 @@
 //! Meta-syntax validation logic of attributes for post-expansion.
 
-use errors::{PResult, Applicability};
+use crate::parse_in;
+
+use rustc_errors::{PResult, Applicability};
 use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
-use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MetaItem, MetaItemKind};
+use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
 use syntax::attr::mk_name_value_item_str;
 use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
+use syntax::tokenstream::DelimSpan;
 use syntax::sess::ParseSess;
 use syntax_pos::{Symbol, sym};
 
@@ -27,9 +30,20 @@
 pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
     Ok(match attr.kind {
         AttrKind::Normal(ref item) => MetaItem {
-            path: item.path.clone(),
-            kind: super::parse_in_attr(sess, attr, |p| p.parse_meta_item_kind())?,
             span: attr.span,
+            path: item.path.clone(),
+            kind: match &attr.get_normal_item().args {
+                MacArgs::Empty => MetaItemKind::Word,
+                MacArgs::Eq(_, t) => {
+                    let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
+                    MetaItemKind::NameValue(v)
+                }
+                MacArgs::Delimited(dspan, delim, t) => {
+                    check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
+                    let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;
+                    MetaItemKind::List(nmis)
+                }
+            }
         },
         AttrKind::DocComment(comment) => {
             mk_name_value_item_str(Ident::new(sym::doc, attr.span), comment, attr.span)
@@ -37,6 +51,24 @@
     })
 }
 
+crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
+    if let ast::MacDelimiter::Parenthesis = delim {
+        return;
+    }
+
+    sess.span_diagnostic
+        .struct_span_err(span.entire(), msg)
+        .multipart_suggestion(
+            "the delimiters should be `(` and `)`",
+            vec![
+                (span.open, "(".to_string()),
+                (span.close, ")".to_string()),
+            ],
+            Applicability::MachineApplicable,
+        )
+        .emit();
+}
+
 /// Checks that the given meta-item is compatible with this `AttributeTemplate`.
 fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool {
     match meta {
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 29cfee8..202b6ae 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -158,14 +158,14 @@
         err.emit();
     }
 
-    fn check_decl_no_pat<F: FnMut(Span, bool)>(decl: &FnDecl, mut report_err: F) {
-        for arg in &decl.inputs {
-            match arg.pat.kind {
+    fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, bool)) {
+        for Param { pat, .. } in &decl.inputs {
+            match pat.kind {
                 PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
                 PatKind::Wild => {}
                 PatKind::Ident(BindingMode::ByValue(Mutability::Mutable), _, None) =>
-                    report_err(arg.pat.span, true),
-                _ => report_err(arg.pat.span, false),
+                    report_err(pat.span, true),
+                _ => report_err(pat.span, false),
             }
         }
     }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 04e233c..e2578d6 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -12,7 +12,7 @@
 use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
 use crate::{ModuleOrUniformRoot, ParentScope, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
 use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
-use crate::{ResolutionError, Determinacy, PathResult, CrateLint};
+use crate::{ResolutionError, VisResolutionError, Determinacy, PathResult, CrateLint};
 
 use rustc::bug;
 use rustc::hir::def::{self, *};
@@ -32,8 +32,7 @@
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
 use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind};
 use syntax::token::{self, Token};
-use syntax::print::pprust;
-use syntax::{span_err, struct_span_err};
+use syntax::span_err;
 use syntax::source_map::{respan, Spanned};
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
@@ -192,14 +191,25 @@
 
 impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
+        self.resolve_visibility_speculative(vis, false).unwrap_or_else(|err| {
+            self.r.report_vis_error(err);
+            ty::Visibility::Public
+        })
+    }
+
+    fn resolve_visibility_speculative<'ast>(
+        &mut self,
+        vis: &'ast ast::Visibility,
+        speculative: bool,
+    ) -> Result<ty::Visibility, VisResolutionError<'ast>> {
         let parent_scope = &self.parent_scope;
         match vis.node {
-            ast::VisibilityKind::Public => ty::Visibility::Public,
+            ast::VisibilityKind::Public => Ok(ty::Visibility::Public),
             ast::VisibilityKind::Crate(..) => {
-                ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+                Ok(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)))
             }
             ast::VisibilityKind::Inherited => {
-                ty::Visibility::Restricted(parent_scope.module.normal_ancestor_id)
+                Ok(ty::Visibility::Restricted(parent_scope.module.normal_ancestor_id))
             }
             ast::VisibilityKind::Restricted { ref path, id, .. } => {
                 // For visibilities we are not ready to provide correct implementation of "uniform
@@ -209,86 +219,67 @@
                 let ident = path.segments.get(0).expect("empty path in visibility").ident;
                 let crate_root = if ident.is_path_segment_keyword() {
                     None
-                } else if ident.span.rust_2018() {
-                    let msg = "relative paths are not supported in visibilities on 2018 edition";
-                    self.r.session.struct_span_err(ident.span, msg)
-                        .span_suggestion(
-                            path.span,
-                            "try",
-                            format!("crate::{}", pprust::path_to_string(&path)),
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
-                    return ty::Visibility::Public;
-                } else {
-                    let ctxt = ident.span.ctxt();
+                } else if ident.span.rust_2015() {
                     Some(Segment::from_ident(Ident::new(
-                        kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ctxt)
+                        kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ident.span.ctxt())
                     )))
+                } else {
+                    return Err(VisResolutionError::Relative2018(ident.span, path));
                 };
 
                 let segments = crate_root.into_iter()
                     .chain(path.segments.iter().map(|seg| seg.into())).collect::<Vec<_>>();
-                let expected_found_error = |this: &Self, res: Res| {
-                    let path_str = Segment::names_to_string(&segments);
-                    struct_span_err!(this.r.session, path.span, E0577,
-                                     "expected module, found {} `{}`", res.descr(), path_str)
-                        .span_label(path.span, "not a module").emit();
-                };
+                let expected_found_error = |res| Err(VisResolutionError::ExpectedFound(
+                    path.span, Segment::names_to_string(&segments), res
+                ));
                 match self.r.resolve_path(
                     &segments,
                     Some(TypeNS),
                     parent_scope,
-                    true,
+                    !speculative,
                     path.span,
                     CrateLint::SimplePath(id),
                 ) {
                     PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
                         let res = module.res().expect("visibility resolved to unnamed block");
-                        self.r.record_partial_res(id, PartialRes::new(res));
+                        if !speculative {
+                            self.r.record_partial_res(id, PartialRes::new(res));
+                        }
                         if module.is_normal() {
                             if res == Res::Err {
-                                ty::Visibility::Public
+                                Ok(ty::Visibility::Public)
                             } else {
                                 let vis = ty::Visibility::Restricted(res.def_id());
                                 if self.r.is_accessible_from(vis, parent_scope.module) {
-                                    vis
+                                    Ok(vis)
                                 } else {
-                                    struct_span_err!(self.r.session, path.span, E0742,
-                                        "visibilities can only be restricted to ancestor modules")
-                                        .emit();
-                                    ty::Visibility::Public
+                                    Err(VisResolutionError::AncestorOnly(path.span))
                                 }
                             }
                         } else {
-                            expected_found_error(self, res);
-                            ty::Visibility::Public
+                            expected_found_error(res)
                         }
                     }
-                    PathResult::Module(..) => {
-                        self.r.session.span_err(path.span, "visibility must resolve to a module");
-                        ty::Visibility::Public
-                    }
-                    PathResult::NonModule(partial_res) => {
-                        expected_found_error(self, partial_res.base_res());
-                        ty::Visibility::Public
-                    }
-                    PathResult::Failed { span, label, suggestion, .. } => {
-                        self.r.report_error(
-                            span, ResolutionError::FailedToResolve { label, suggestion }
-                        );
-                        ty::Visibility::Public
-                    }
-                    PathResult::Indeterminate => {
-                        span_err!(self.r.session, path.span, E0578,
-                                  "cannot determine resolution for the visibility");
-                        ty::Visibility::Public
-                    }
+                    PathResult::Module(..) =>
+                        Err(VisResolutionError::ModuleOnly(path.span)),
+                    PathResult::NonModule(partial_res) =>
+                        expected_found_error(partial_res.base_res()),
+                    PathResult::Failed { span, label, suggestion, .. } =>
+                        Err(VisResolutionError::FailedToResolve(span, label, suggestion)),
+                    PathResult::Indeterminate =>
+                        Err(VisResolutionError::Indeterminate(path.span)),
                 }
             }
         }
     }
 
+    fn insert_field_names_local(&mut self, def_id: DefId, vdata: &ast::VariantData) {
+        let field_names = vdata.fields().iter().map(|field| {
+            respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name))
+        }).collect();
+        self.insert_field_names(def_id, field_names);
+    }
+
     fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Spanned<Name>>) {
         if !field_names.is_empty() {
             self.r.field_names.insert(def_id, field_names);
@@ -656,8 +647,6 @@
                 self.r.define(parent, ident, TypeNS, imported_binding);
             }
 
-            ItemKind::GlobalAsm(..) => {}
-
             ItemKind::Mod(..) if ident.name == kw::Invalid => {} // Crate root
 
             ItemKind::Mod(..) => {
@@ -676,9 +665,6 @@
                 self.parent_scope.module = module;
             }
 
-            // Handled in `rustc_metadata::{native_libs,link_args}`
-            ItemKind::ForeignMod(..) => {}
-
             // These items live in the value namespace.
             ItemKind::Static(..) => {
                 let res = Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id));
@@ -726,65 +712,52 @@
             }
 
             // These items live in both the type and value namespaces.
-            ItemKind::Struct(ref struct_def, _) => {
+            ItemKind::Struct(ref vdata, _) => {
                 // Define a name in the type namespace.
                 let def_id = self.r.definitions.local_def_id(item.id);
                 let res = Res::Def(DefKind::Struct, def_id);
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
 
-                let mut ctor_vis = vis;
-
-                let has_non_exhaustive = attr::contains_name(&item.attrs, sym::non_exhaustive);
-
-                // If the structure is marked as non_exhaustive then lower the visibility
-                // to within the crate.
-                if has_non_exhaustive && vis == ty::Visibility::Public {
-                    ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
-                }
-
                 // Record field names for error reporting.
-                let field_names = struct_def.fields().iter().map(|field| {
-                    // NOTE: The field may be an expansion placeholder, but expansion sets correct
-                    // visibilities for unnamed field placeholders specifically, so the constructor
-                    // visibility should still be determined correctly.
-                    let field_vis = self.resolve_visibility(&field.vis);
-                    if ctor_vis.is_at_least(field_vis, &*self.r) {
-                        ctor_vis = field_vis;
-                    }
-                    respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name))
-                }).collect();
-                let item_def_id = self.r.definitions.local_def_id(item.id);
-                self.insert_field_names(item_def_id, field_names);
+                self.insert_field_names_local(def_id, vdata);
 
                 // If this is a tuple or unit struct, define a name
                 // in the value namespace as well.
-                if let Some(ctor_node_id) = struct_def.ctor_id() {
+                if let Some(ctor_node_id) = vdata.ctor_id() {
+                    let mut ctor_vis = vis;
+                    // If the structure is marked as non_exhaustive then lower the visibility
+                    // to within the crate.
+                    if vis == ty::Visibility::Public &&
+                       attr::contains_name(&item.attrs, sym::non_exhaustive) {
+                        ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
+                    }
+                    for field in vdata.fields() {
+                        // NOTE: The field may be an expansion placeholder, but expansion sets
+                        // correct visibilities for unnamed field placeholders specifically, so the
+                        // constructor visibility should still be determined correctly.
+                        if let Ok(field_vis) =
+                                self.resolve_visibility_speculative(&field.vis, true) {
+                            if ctor_vis.is_at_least(field_vis, &*self.r) {
+                                ctor_vis = field_vis;
+                            }
+                        }
+                    }
                     let ctor_res = Res::Def(
-                        DefKind::Ctor(CtorOf::Struct, CtorKind::from_ast(struct_def)),
+                        DefKind::Ctor(CtorOf::Struct, CtorKind::from_ast(vdata)),
                         self.r.definitions.local_def_id(ctor_node_id),
                     );
                     self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
-                    self.r.struct_constructors.insert(res.def_id(), (ctor_res, ctor_vis));
+                    self.r.struct_constructors.insert(def_id, (ctor_res, ctor_vis));
                 }
             }
 
             ItemKind::Union(ref vdata, _) => {
-                let res = Res::Def(DefKind::Union, self.r.definitions.local_def_id(item.id));
+                let def_id = self.r.definitions.local_def_id(item.id);
+                let res = Res::Def(DefKind::Union, def_id);
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
 
                 // Record field names for error reporting.
-                let field_names = vdata.fields().iter().map(|field| {
-                    self.resolve_visibility(&field.vis);
-                    respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name))
-                }).collect();
-                let item_def_id = self.r.definitions.local_def_id(item.id);
-                self.insert_field_names(item_def_id, field_names);
-            }
-
-            ItemKind::Impl(.., ref impl_items) => {
-                for impl_item in impl_items {
-                    self.resolve_visibility(&impl_item.vis);
-                }
+                self.insert_field_names_local(def_id, vdata);
             }
 
             ItemKind::Trait(..) => {
@@ -801,6 +774,9 @@
                 self.parent_scope.module = module;
             }
 
+            // These items do not add names to modules.
+            ItemKind::Impl(..) | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
+
             ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
         }
     }
@@ -1134,7 +1110,6 @@
 }
 
 impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
-    method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item);
     method!(visit_expr:      ast::Expr,     ast::ExprKind::Mac,       walk_expr);
     method!(visit_pat:       ast::Pat,      ast::PatKind::Mac,        walk_pat);
     method!(visit_ty:        ast::Ty,       ast::TyKind::Mac,         walk_ty);
@@ -1218,6 +1193,15 @@
         visit::walk_trait_item(self, item);
     }
 
+    fn visit_impl_item(&mut self, item: &'b ast::ImplItem) {
+        if let ast::ImplItemKind::Macro(..) = item.kind {
+            self.visit_invoc(item.id);
+        } else {
+            self.resolve_visibility(&item.vis);
+            visit::walk_impl_item(self, item);
+        }
+    }
+
     fn visit_token(&mut self, t: Token) {
         if let token::Interpolated(nt) = t.kind {
             if let token::NtExpr(ref expr) = *nt {
@@ -1281,6 +1265,7 @@
         if sf.is_placeholder {
             self.visit_invoc(sf.id);
         } else {
+            self.resolve_visibility(&sf.vis);
             visit::walk_struct_field(self, sf);
         }
     }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 4dcafb6..f92415f 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -11,6 +11,7 @@
 use rustc::util::nodemap::FxHashSet;
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use syntax::ast::{self, Ident, Path};
+use syntax::print::pprust;
 use syntax::source_map::SourceMap;
 use syntax::struct_span_err;
 use syntax::symbol::{Symbol, kw};
@@ -22,6 +23,7 @@
 use crate::path_names_to_string;
 use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
 use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment};
+use crate::VisResolutionError;
 
 use rustc_error_codes::*;
 
@@ -357,6 +359,44 @@
         }
     }
 
+    crate fn report_vis_error(&self, vis_resolution_error: VisResolutionError<'_>) {
+        match vis_resolution_error {
+            VisResolutionError::Relative2018(span, path) => {
+                let mut err = self.session.struct_span_err(span,
+                    "relative paths are not supported in visibilities on 2018 edition");
+                err.span_suggestion(
+                    path.span,
+                    "try",
+                    format!("crate::{}", pprust::path_to_string(&path)),
+                    Applicability::MaybeIncorrect,
+                );
+                err
+            }
+            VisResolutionError::AncestorOnly(span) => {
+                struct_span_err!(self.session, span, E0742,
+                    "visibilities can only be restricted to ancestor modules")
+            }
+            VisResolutionError::FailedToResolve(span, label, suggestion) => {
+                self.into_struct_error(
+                    span, ResolutionError::FailedToResolve { label, suggestion }
+                )
+            }
+            VisResolutionError::ExpectedFound(span, path_str, res) => {
+                let mut err = struct_span_err!(self.session, span, E0577,
+                    "expected module, found {} `{}`", res.descr(), path_str);
+                err.span_label(span, "not a module");
+                err
+            }
+            VisResolutionError::Indeterminate(span) => {
+                struct_span_err!(self.session, span, E0578,
+                    "cannot determine resolution for the visibility")
+            }
+            VisResolutionError::ModuleOnly(span) => {
+                self.session.struct_span_err(span, "visibility must resolve to a module")
+            }
+        }.emit()
+    }
+
     /// Lookup typo candidate in scope for a macro or import.
     fn early_lookup_typo_candidate(
         &mut self,
@@ -422,11 +462,7 @@
                 Scope::MacroUsePrelude => {
                     suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
                         let res = binding.res();
-                        if filter_fn(res) {
-                            Some(TypoSuggestion::from_res(*name, res))
-                        } else {
-                            None
-                        }
+                        filter_fn(res).then_some(TypoSuggestion::from_res(*name, res))
                     }));
                 }
                 Scope::BuiltinAttrs => {
@@ -440,11 +476,7 @@
                 Scope::ExternPrelude => {
                     suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
                         let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX));
-                        if filter_fn(res) {
-                            Some(TypoSuggestion::from_res(ident.name, res))
-                        } else {
-                            None
-                        }
+                        filter_fn(res).then_some(TypoSuggestion::from_res(ident.name, res))
                     }));
                 }
                 Scope::ToolPrelude => {
@@ -467,11 +499,7 @@
                     suggestions.extend(
                         primitive_types.iter().flat_map(|(name, prim_ty)| {
                             let res = Res::PrimTy(*prim_ty);
-                            if filter_fn(res) {
-                                Some(TypoSuggestion::from_res(*name, res))
-                            } else {
-                                None
-                            }
+                            filter_fn(res).then_some(TypoSuggestion::from_res(*name, res))
                         })
                     )
                 }
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 666c482..4f95d6f 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -496,11 +496,7 @@
                 GenericParamKind::Lifetime { .. } => None,
                 GenericParamKind::Type { ref default, .. } => {
                     found_default |= default.is_some();
-                    if found_default {
-                        Some((Ident::with_dummy_span(param.ident.name), Res::Err))
-                    } else {
-                        None
-                    }
+                    found_default.then_some((Ident::with_dummy_span(param.ident.name), Res::Err))
                 }
             }));
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index be36e02..d365624 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -9,6 +9,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
 #![feature(nll)]
@@ -217,6 +218,15 @@
     SelfInTyParamDefault,
 }
 
+enum VisResolutionError<'a> {
+    Relative2018(Span, &'a ast::Path),
+    AncestorOnly(Span),
+    FailedToResolve(Span, String, Option<Suggestion>),
+    ExpectedFound(Span, String, Res),
+    Indeterminate(Span),
+    ModuleOnly(Span),
+}
+
 // A minimal representation of a path segment. We use this in resolve because
 // we synthesize 'path segments' which don't have the rest of an AST or HIR
 // `PathSegment`.
@@ -1126,8 +1136,10 @@
         definitions.create_root_def(crate_name, session.local_crate_disambiguator());
 
         let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> =
-            session.opts.externs.iter().map(|kv| (Ident::from_str(kv.0), Default::default()))
-                                       .collect();
+            session.opts.externs.iter()
+                .filter(|(_, entry)| entry.add_prelude)
+                .map(|(name, _)| (Ident::from_str(name), Default::default()))
+                .collect();
 
         if !attr::contains_name(&krate.attrs, sym::no_core) {
             extern_prelude.insert(Ident::with_dummy_span(sym::core), Default::default());
diff --git a/src/librustc_session/code_stats.rs b/src/librustc_session/code_stats.rs
index 5baf0c5..764d6d8 100644
--- a/src/librustc_session/code_stats.rs
+++ b/src/librustc_session/code_stats.rs
@@ -132,9 +132,12 @@
 
                 let mut min_offset = discr_size;
 
-                // We want to print fields by increasing offset.
+                // We want to print fields by increasing offset. We also want
+                // zero-sized fields before non-zero-sized fields, otherwise
+                // the loop below goes wrong; hence the `f.size` in the sort
+                // key.
                 let mut fields = fields.clone();
-                fields.sort_by_key(|f| f.offset);
+                fields.sort_by_key(|f| (f.offset, f.size));
 
                 for field in fields.iter() {
                     let FieldInfo { ref name, offset, size, align } = *field;
@@ -146,7 +149,7 @@
                     }
 
                     if offset < min_offset {
-                        // if this happens something is very wrong
+                        // If this happens it's probably a union.
                         println!("print-type-size {}field `.{}`: {} bytes, \
                                   offset: {} bytes, \
                                   alignment: {} bytes",
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index 58113bb..7f3bab8 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
 //! Contains infrastructure for configuring the compiler, including parsing
 //! command-line options.
 
@@ -31,7 +33,7 @@
 use std::str::{self, FromStr};
 use std::hash::Hasher;
 use std::collections::hash_map::DefaultHasher;
-use std::iter::FromIterator;
+use std::iter::{self, FromIterator};
 use std::path::{Path, PathBuf};
 
 pub struct Config {
@@ -322,10 +324,35 @@
 #[derive(Clone)]
 pub struct Externs(BTreeMap<String, ExternEntry>);
 
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug)]
 pub struct ExternEntry {
-    pub locations: BTreeSet<Option<String>>,
-    pub is_private_dep: bool
+    pub location: ExternLocation,
+    /// Indicates this is a "private" dependency for the
+    /// `exported_private_dependencies` lint.
+    ///
+    /// This can be set with the `priv` option like
+    /// `--extern priv:name=foo.rlib`.
+    pub is_private_dep: bool,
+    /// Add the extern entry to the extern prelude.
+    ///
+    /// This can be disabled with the `noprelude` option like
+    /// `--extern noprelude:name`.
+    pub add_prelude: bool,
+}
+
+#[derive(Clone, Debug)]
+pub enum ExternLocation {
+    /// Indicates to look for the library in the search paths.
+    ///
+    /// Added via `--extern name`.
+    FoundInLibrarySearchDirectories,
+    /// The locations where this extern entry must be found.
+    ///
+    /// The `CrateLoader` is responsible for loading these and figuring out
+    /// which one to use.
+    ///
+    /// Added via `--extern prelude_name=some_file.rlib`
+    ExactPaths(BTreeSet<String>),
 }
 
 impl Externs {
@@ -342,6 +369,18 @@
     }
 }
 
+impl ExternEntry {
+    fn new(location: ExternLocation) -> ExternEntry {
+        ExternEntry { location, is_private_dep: false, add_prelude: false }
+    }
+
+    pub fn files(&self) -> Option<impl Iterator<Item = &String>> {
+        match &self.location {
+            ExternLocation::ExactPaths(set) => Some(set.iter()),
+            _ => None,
+        }
+    }
+}
 
 macro_rules! hash_option {
     ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => ({});
@@ -1869,12 +1908,6 @@
             "Specify where an external rust library is located",
             "NAME[=PATH]",
         ),
-        opt::multi_s(
-            "",
-            "extern-private",
-            "Specify where an extern rust library is located, marking it as a private dependency",
-            "NAME=PATH",
-        ),
         opt::opt_s("", "sysroot", "Override the system root", "PATH"),
         opt::multi("Z", "", "Set internal debugging options", "FLAG"),
         opt::opt_s(
@@ -2435,43 +2468,105 @@
     }
 }
 
-fn parse_externs(
+pub fn parse_externs(
     matches: &getopts::Matches,
     debugging_opts: &DebuggingOptions,
     error_format: ErrorOutputType,
 ) -> Externs {
-    if matches.opt_present("extern-private") && !debugging_opts.unstable_options {
-        early_error(
-            ErrorOutputType::default(),
-            "'--extern-private' is unstable and only \
-            available for nightly builds of rustc."
-        )
-    }
-
-    // We start out with a `Vec<(Option<String>, bool)>>`,
-    // and later convert it into a `BTreeSet<(Option<String>, bool)>`
-    // This allows to modify entries in-place to set their correct
-    // 'public' value.
+    let is_unstable_enabled = debugging_opts.unstable_options;
     let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
-    for (arg, private) in matches.opt_strs("extern").into_iter().map(|v| (v, false))
-        .chain(matches.opt_strs("extern-private").into_iter().map(|v| (v, true))) {
-
+    for arg in matches.opt_strs("extern") {
         let mut parts = arg.splitn(2, '=');
-        let name = parts.next().unwrap_or_else(||
-            early_error(error_format, "--extern value must not be empty"));
-        let location = parts.next().map(|s| s.to_string());
+        let name = parts
+            .next()
+            .unwrap_or_else(|| early_error(error_format, "--extern value must not be empty"));
+        let path = parts.next().map(|s| s.to_string());
 
-        let entry = externs
-            .entry(name.to_owned())
-            .or_default();
+        let mut name_parts = name.splitn(2, ':');
+        let first_part = name_parts.next();
+        let second_part = name_parts.next();
+        let (options, name) = match (first_part, second_part) {
+            (Some(opts), Some(name)) => (Some(opts), name),
+            (Some(name), None) => (None, name),
+            (None, None) => early_error(error_format, "--extern name must not be empty"),
+            _ => unreachable!(),
+        };
 
+        let entry = externs.entry(name.to_owned());
 
-        entry.locations.insert(location.clone());
+        use std::collections::btree_map::Entry;
 
-        // Crates start out being not private,
-        // and go to being private if we see an '--extern-private'
-        // flag
-        entry.is_private_dep |= private;
+        let entry = if let Some(path) = path {
+            // --extern prelude_name=some_file.rlib
+            match entry {
+                Entry::Vacant(vacant) => {
+                    let files = BTreeSet::from_iter(iter::once(path));
+                    vacant.insert(ExternEntry::new(ExternLocation::ExactPaths(files)))
+                }
+                Entry::Occupied(occupied) => {
+                    let ext_ent = occupied.into_mut();
+                    match ext_ent {
+                        ExternEntry { location: ExternLocation::ExactPaths(files), .. } => {
+                            files.insert(path);
+                        }
+                        ExternEntry {
+                            location: location @ ExternLocation::FoundInLibrarySearchDirectories,
+                            ..
+                        } => {
+                            // Exact paths take precedence over search directories.
+                            let files = BTreeSet::from_iter(iter::once(path));
+                            *location = ExternLocation::ExactPaths(files);
+                        }
+                    }
+                    ext_ent
+                }
+            }
+        } else {
+            // --extern prelude_name
+            match entry {
+                Entry::Vacant(vacant) => {
+                    vacant.insert(ExternEntry::new(ExternLocation::FoundInLibrarySearchDirectories))
+                }
+                Entry::Occupied(occupied) => {
+                    // Ignore if already specified.
+                    occupied.into_mut()
+                }
+            }
+        };
+
+        let mut is_private_dep = false;
+        let mut add_prelude = true;
+        if let Some(opts) = options {
+            if !is_unstable_enabled {
+                early_error(
+                    error_format,
+                    "the `-Z unstable-options` flag must also be passed to \
+                     enable `--extern options",
+                );
+            }
+            for opt in opts.split(',') {
+                match opt {
+                    "priv" => is_private_dep = true,
+                    "noprelude" => {
+                        if let ExternLocation::ExactPaths(_) = &entry.location {
+                            add_prelude = false;
+                        } else {
+                            early_error(
+                                error_format,
+                                "the `noprelude` --extern option requires a file path",
+                            );
+                        }
+                    }
+                    _ => early_error(error_format, &format!("unknown --extern option `{}`", opt)),
+                }
+            }
+        }
+
+        // Crates start out being not private, and go to being private `priv`
+        // is specified.
+        entry.is_private_dep |= is_private_dep;
+        // If any flag is missing `noprelude`, then add to the prelude.
+        entry.add_prelude |= add_prelude;
     }
     Externs(externs)
 }
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index 9369c17..150d207 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -752,11 +752,7 @@
     }
 
     pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<'_, PathBuf>> {
-        if self.opts.incremental.is_some() {
-            Some(self.incr_comp_session_dir())
-        } else {
-            None
-        }
+        self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir())
     }
 
     pub fn print_perf_stats(&self) {
@@ -1079,8 +1075,9 @@
                     None
                 }
             }
-        }
-        else { None };
+        } else {
+            None
+        };
 
     let host_triple = TargetTriple::from_triple(config::host_triple());
     let host = Target::search(&host_triple).unwrap_or_else(|e|
diff --git a/src/librustc_target/abi/call/aarch64.rs b/src/librustc_target/abi/call/aarch64.rs
index 45fe475..06c001e 100644
--- a/src/librustc_target/abi/call/aarch64.rs
+++ b/src/librustc_target/abi/call/aarch64.rs
@@ -20,14 +20,7 @@
             RegKind::Vector => size.bits() == 64 || size.bits() == 128
         };
 
-        if valid_unit {
-            Some(Uniform {
-                unit,
-                total: size
-            })
-        } else {
-            None
-        }
+        valid_unit.then_some(Uniform { unit, total: size })
     })
 }
 
diff --git a/src/librustc_target/abi/call/arm.rs b/src/librustc_target/abi/call/arm.rs
index ff929f3..36971c1 100644
--- a/src/librustc_target/abi/call/arm.rs
+++ b/src/librustc_target/abi/call/arm.rs
@@ -21,14 +21,7 @@
             RegKind::Vector => size.bits() == 64 || size.bits() == 128
         };
 
-        if valid_unit {
-            Some(Uniform {
-                unit,
-                total: size
-            })
-        } else {
-            None
-        }
+        valid_unit.then_some(Uniform { unit, total: size })
     })
 }
 
diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs
index 6f53577..5119464 100644
--- a/src/librustc_target/abi/call/mod.rs
+++ b/src/librustc_target/abi/call/mod.rs
@@ -416,11 +416,7 @@
         // i686-pc-windows-msvc, it results in wrong stack offsets.
         // attrs.pointee_align = Some(self.layout.align.abi);
 
-        let extra_attrs = if self.layout.is_unsized() {
-            Some(ArgAttributes::new())
-        } else {
-            None
-        };
+        let extra_attrs = self.layout.is_unsized().then_some(ArgAttributes::new());
 
         self.mode = PassMode::Indirect(attrs, extra_attrs);
     }
diff --git a/src/librustc_target/abi/call/powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs
index f967a83..fe45948 100644
--- a/src/librustc_target/abi/call/powerpc64.rs
+++ b/src/librustc_target/abi/call/powerpc64.rs
@@ -32,14 +32,7 @@
             RegKind::Vector => arg.layout.size.bits() == 128
         };
 
-        if valid_unit {
-            Some(Uniform {
-                unit,
-                total: arg.layout.size
-            })
-        } else {
-            None
-        }
+        valid_unit.then_some(Uniform { unit, total: arg.layout.size })
     })
 }
 
diff --git a/src/librustc_target/abi/call/sparc64.rs b/src/librustc_target/abi/call/sparc64.rs
index fe2c427..32be7b8 100644
--- a/src/librustc_target/abi/call/sparc64.rs
+++ b/src/librustc_target/abi/call/sparc64.rs
@@ -20,14 +20,7 @@
             RegKind::Vector => arg.layout.size.bits() == 128
         };
 
-        if valid_unit {
-            Some(Uniform {
-                unit,
-                total: arg.layout.size
-            })
-        } else {
-            None
-        }
+        valid_unit.then_some(Uniform { unit, total: arg.layout.size })
     })
 }
 
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index ac78181..b0bc052 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -802,6 +802,14 @@
             _ => false,
         }
     }
+
+    /// Returns `true` is this is a scalar type
+    pub fn is_scalar(&self) -> bool {
+        match *self {
+            Abi::Scalar(_) => true,
+            _ => false,
+        }
+    }
 }
 
 rustc_index::newtype_index! {
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index 5582eaf..6a1498e 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -10,6 +10,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(box_syntax)]
+#![feature(bool_to_option)]
 #![feature(nll)]
 #![feature(slice_patterns)]
 
diff --git a/src/librustc_target/spec/wasm32_base.rs b/src/librustc_target/spec/wasm32_base.rs
index 6f00245..e18a9e6 100644
--- a/src/librustc_target/spec/wasm32_base.rs
+++ b/src/librustc_target/spec/wasm32_base.rs
@@ -140,6 +140,9 @@
         has_elf_tls: true,
         tls_model: "local-exec".to_string(),
 
+        // gdb scripts don't work on wasm blobs
+        emit_debug_gdb_scripts: false,
+
         .. Default::default()
     }
 }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 901a219..726b3ba 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1284,9 +1284,25 @@
                     augment_error(&mut err);
                 }
 
+                if let Some(expr) = expression {
+                    fcx.emit_coerce_suggestions(&mut err, expr, found, expected);
+                }
+
                 // Error possibly reported in `check_assign` so avoid emitting error again.
-                err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected))
-                    .is_some());
+                let assign_to_bool = expression
+                    // #67273: Use initial expected type as opposed to `expected`.
+                    // Otherwise we end up using prior coercions in e.g. a `match` expression:
+                    // ```
+                    // match i {
+                    //     0 => true, // Because of this...
+                    //     1 => i = 1, // ...`expected == bool` now, but not when checking `i = 1`.
+                    //     _ => (),
+                    // };
+                    // ```
+                    .filter(|e| fcx.is_assign_to_bool(e, self.expected_ty()))
+                    .is_some();
+
+                err.emit_unless(assign_to_bool);
 
                 self.final_ty = Some(fcx.tcx.types.err);
             }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 4331d44..16a55d2 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -15,6 +15,22 @@
 use super::method::probe;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+
+    pub fn emit_coerce_suggestions(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expr: &hir::Expr,
+        expr_ty: Ty<'tcx>,
+        expected: Ty<'tcx>
+    ) {
+        self.annotate_expected_due_to_let_ty(err, expr);
+        self.suggest_compatible_variants(err, expr, expected, expr_ty);
+        self.suggest_ref_or_into(err, expr, expected, expr_ty);
+        self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
+        self.suggest_missing_await(err, expr, expected, expr_ty);
+    }
+
+
     // Requires that the two types unify, and prints an error message if
     // they don't.
     pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
@@ -65,13 +81,13 @@
         }
     }
 
-    pub fn demand_eqtype_pat(
+    pub fn demand_eqtype_pat_diag(
         &self,
         cause_span: Span,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
         match_expr_span: Option<Span>,
-    ) {
+    ) -> Option<DiagnosticBuilder<'tcx>> {
         let cause = if let Some(span) = match_expr_span {
             self.cause(
                 cause_span,
@@ -80,9 +96,19 @@
         } else {
             self.misc(cause_span)
         };
-        self.demand_eqtype_with_origin(&cause, expected, actual).map(|mut err| err.emit());
+        self.demand_eqtype_with_origin(&cause, expected, actual)
     }
 
+    pub fn demand_eqtype_pat(
+        &self,
+        cause_span: Span,
+        expected: Ty<'tcx>,
+        actual: Ty<'tcx>,
+        match_expr_span: Option<Span>,
+    ) {
+        self.demand_eqtype_pat_diag(cause_span, expected, actual, match_expr_span)
+            .map(|mut err| err.emit());
+    }
 
     pub fn demand_coerce(&self,
                          expr: &hir::Expr,
@@ -127,11 +153,7 @@
             return (expected, None)
         }
 
-        self.annotate_expected_due_to_let_ty(&mut err, expr);
-        self.suggest_compatible_variants(&mut err, expr, expected, expr_ty);
-        self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
-        self.suggest_boxing_when_appropriate(&mut err, expr, expected, expr_ty);
-        self.suggest_missing_await(&mut err, expr, expected, expr_ty);
+        self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected);
 
         (expected, Some(err))
     }
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 4766360..fc7d197 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -582,11 +582,21 @@
                 // If this is a break with a value, we need to type-check
                 // the expression. Get an expected type from the loop context.
                 let opt_coerce_to = {
+                    // We should release `enclosing_breakables` before the `check_expr_with_hint`
+                    // below, so can't move this block of code to the enclosing scope and share
+                    // `ctxt` with the second `encloding_breakables` borrow below.
                     let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
-                    enclosing_breakables.find_breakable(target_id)
-                                        .coerce
-                                        .as_ref()
-                                        .map(|coerce| coerce.expected_ty())
+                    match enclosing_breakables.opt_find_breakable(target_id) {
+                        Some(ctxt) =>
+                            ctxt.coerce.as_ref().map(|coerce| coerce.expected_ty()),
+                        None => { // Avoid ICE when `break` is inside a closure (#65383).
+                            self.tcx.sess.delay_span_bug(
+                                expr.span,
+                                "break was outside loop, but no error was emitted",
+                            );
+                            return tcx.types.err;
+                        }
+                    }
                 };
 
                 // If the loop context is not a `loop { }`, then break with
@@ -861,6 +871,9 @@
 
         let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr) {
             Ok(method) => {
+                // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
+                // trigger this codepath causing `structuraly_resolved_type` to emit an error.
+
                 self.write_method_call(expr.hir_id, method);
                 Ok(method)
             }
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 9f034e65..cec8311 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -1,7 +1,6 @@
 //! Type-checking for the rust-intrinsic and platform-intrinsic
 //! intrinsics that the compiler exposes.
 
-use rustc::middle::lang_items::PanicLocationLangItem;
 use rustc::traits::{ObligationCause, ObligationCauseCode};
 use rustc::ty::{self, TyCtxt, Ty};
 use rustc::ty::subst::Subst;
@@ -148,15 +147,7 @@
                  ], tcx.types.usize)
             }
             "rustc_peek" => (1, vec![param(0)], param(0)),
-            "caller_location" => (
-                0,
-                vec![],
-                tcx.mk_imm_ref(
-                    tcx.lifetimes.re_static,
-                    tcx.type_of(tcx.require_lang_item(PanicLocationLangItem, None))
-                        .subst(tcx, tcx.mk_substs([tcx.lifetimes.re_static.into()].iter())),
-                ),
-            ),
+            "caller_location" => (0, vec![], tcx.caller_location_ty()),
             "panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()),
             "init" => (1, Vec::new(), param(0)),
             "uninit" => (1, Vec::new(), param(0)),
@@ -336,6 +327,7 @@
                 (1, vec![param(0), param(0)], param(0)),
             "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" =>
                 (1, vec![param(0), param(0)], param(0)),
+            "float_to_int_approx_unchecked" => (2, vec![ param(0) ], param(1)),
 
             "assume" => (0, vec![tcx.types.bool], tcx.mk_unit()),
             "likely" => (0, vec![tcx.types.bool], tcx.types.bool),
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 9717190..9923081 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1105,11 +1105,7 @@
             r.map(|mut pick| {
                 pick.autoderefs = step.autoderefs;
                 pick.autoref = Some(mutbl);
-                pick.unsize = if step.unsize {
-                    Some(self_ty)
-                } else {
-                    None
-                };
+                pick.unsize = step.unsize.then_some(self_ty);
                 pick
             })
         })
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index c7a0190..43e7bbc 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -103,6 +103,7 @@
 use rustc_target::spec::abi::Abi;
 use rustc::infer::opaque_types::OpaqueTypeDecl;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc::middle::region;
 use rustc::mir::interpret::{ConstValue, GlobalId};
@@ -4584,8 +4585,6 @@
             pointing_at_return_type = self.suggest_missing_return_type(
                 err, &fn_decl, expected, found, can_suggest);
         }
-        self.suggest_ref_or_into(err, expr, expected, found);
-        self.suggest_boxing_when_appropriate(err, expr, expected, found);
         pointing_at_return_type
     }
 
@@ -4957,7 +4956,9 @@
                     ty: expected,
                 }));
                 let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
+                debug!("suggest_missing_await: trying obligation {:?}", obligation);
                 if self.infcx.predicate_may_hold(&obligation) {
+                    debug!("suggest_missing_await: obligation held: {:?}", obligation);
                     if let Ok(code) = self.sess().source_map().span_to_snippet(sp) {
                         err.span_suggestion(
                             sp,
@@ -4965,7 +4966,11 @@
                             format!("{}.await", code),
                             Applicability::MaybeIncorrect,
                         );
+                    } else {
+                        debug!("suggest_missing_await: no snippet for {:?}", sp);
                     }
+                } else {
+                    debug!("suggest_missing_await: obligation did not hold: {:?}", obligation)
                 }
             }
         }
@@ -5355,7 +5360,7 @@
             ty
         } else {
             if !self.is_tainted_by_errors() {
-                self.need_type_info_err((**self).body_id, sp, ty)
+                self.need_type_info_err((**self).body_id, sp, ty, E0282)
                     .note("type must be known at this point")
                     .emit();
             }
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 9dd3bc6..71d1cd8 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -703,7 +703,10 @@
         let pat_ty = pat_ty.fn_sig(tcx).output();
         let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
 
-        self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
+        // Type-check the tuple struct pattern against the expected type.
+        let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, match_arm_pat_span);
+        let had_err = diag.is_some();
+        diag.map(|mut err| err.emit());
 
         // Type-check subpatterns.
         if subpats.len() == variant.fields.len()
@@ -721,7 +724,7 @@
             }
         } else {
             // Pattern has wrong number of fields.
-            self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected);
+            self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
             on_error();
             return tcx.types.err;
         }
@@ -734,8 +737,9 @@
         res: Res,
         qpath: &hir::QPath,
         subpats: &'tcx [P<Pat>],
-        fields: &[ty::FieldDef],
-        expected: Ty<'tcx>
+        fields: &'tcx [ty::FieldDef],
+        expected: Ty<'tcx>,
+        had_err: bool,
     ) {
         let subpats_ending = pluralize!(subpats.len());
         let fields_ending = pluralize!(fields.len());
@@ -763,9 +767,12 @@
         // More generally, the expected type wants a tuple variant with one field of an
         // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
         // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
-        let missing_parenthesis = match expected.kind {
-            ty::Adt(_, substs) if fields.len() == 1 => {
-                let field_ty = fields[0].ty(self.tcx, substs);
+        let missing_parenthesis = match (&expected.kind, fields, had_err) {
+            // #67037: only do this if we could sucessfully type-check the expected type against
+            // the tuple struct pattern. Otherwise the substs could get out of range on e.g.,
+            // `let P() = U;` where `P != U` with `struct P<T>(T);`.
+            (ty::Adt(_, substs), [field], false) => {
+                let field_ty = self.field_ty(pat_span, field, substs);
                 match field_ty.kind {
                     ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(),
                     _ => false,
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 3002459..c5a6c07 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -114,11 +114,7 @@
         };
 
         let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs {
-            if self.closure_kind(closure_def_id, closure_substs).is_none() {
-                Some(closure_substs)
-            } else {
-                None
-            }
+            self.closure_kind(closure_def_id, closure_substs).is_none().then_some(closure_substs)
         } else {
             None
         };
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 3113e9b..35f25b3 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -8,6 +8,7 @@
 use rustc::hir::def_id::{DefId, DefIndex};
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::infer::InferCtxt;
+use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc::ty::fold::{TypeFoldable, TypeFolder};
 use rustc::ty::{self, Ty, TyCtxt};
@@ -717,7 +718,7 @@
     fn report_error(&self, t: Ty<'tcx>) {
         if !self.tcx.sess.has_errors() {
             self.infcx
-                .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t)
+                .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, E0282)
                 .emit();
         }
     }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 6d6e768..b982979 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -2616,7 +2616,7 @@
                     tcx.sess,
                     attr.span,
                     E0737,
-                    "Rust ABI is required to use `#[track_caller]`"
+                    "`#[track_caller]` requires Rust ABI"
                 ).emit();
             }
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index c606fea..6a6294b 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -59,6 +59,7 @@
 
 #![allow(non_camel_case_types)]
 
+#![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index e3de7fe..f282291 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -12,4 +12,6 @@
 pulldown-cmark = { version = "0.5.3", default-features = false }
 minifier = "0.0.33"
 rayon = { version = "0.3.0", package = "rustc-rayon" }
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
 tempfile = "3"
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index b7f5ed9..e198b00 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -1,10 +1,24 @@
 use rustc::hir;
 use rustc::traits::auto_trait::{self, AutoTraitResult};
-use rustc::ty::{self, TypeFoldable};
+use rustc::ty::{self, Region, RegionVid, TypeFoldable};
+use rustc::util::nodemap::FxHashSet;
+
 use std::fmt::Debug;
 
 use super::*;
 
+#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
+enum RegionTarget<'tcx> {
+    Region(Region<'tcx>),
+    RegionVid(RegionVid)
+}
+
+#[derive(Default, Debug, Clone)]
+struct RegionDeps<'tcx> {
+    larger: FxHashSet<RegionTarget<'tcx>>,
+    smaller: FxHashSet<RegionTarget<'tcx>>
+}
+
 pub struct AutoTraitFinder<'a, 'tcx> {
     pub cx: &'a core::DocContext<'tcx>,
     pub f: auto_trait::AutoTraitFinder<'tcx>,
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 078948c..fb2cce3 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -209,6 +209,9 @@
 
 impl ops::BitAndAssign for Cfg {
     fn bitand_assign(&mut self, other: Cfg) {
+        if *self == other {
+            return;
+        }
         match (self, other) {
             (&mut Cfg::False, _) | (_, Cfg::True) => {},
             (s, Cfg::False) => *s = Cfg::False,
@@ -238,6 +241,9 @@
 
 impl ops::BitOrAssign for Cfg {
     fn bitor_assign(&mut self, other: Cfg) {
+        if *self == other {
+            return;
+        }
         match (self, other) {
             (&mut Cfg::True, _) | (_, Cfg::False) => {},
             (s, Cfg::True) => *s = Cfg::True,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 4d8d004..e5f684c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1,16 +1,15 @@
-// ignore-tidy-filelength
-
 //! This module contains the "cleaned" pieces of the AST, and the functions
 //! that clean them.
 
 pub mod inline;
 pub mod cfg;
-mod simplify;
+pub mod utils;
 mod auto_trait;
 mod blanket_impl;
+mod simplify;
+pub mod types;
 
 use rustc_index::vec::{IndexVec, Idx};
-use rustc_target::spec::abi::Abi;
 use rustc_typeck::hir_ty_to_ty;
 use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
 use rustc::middle::resolve_lifetime as rl;
@@ -19,63 +18,42 @@
 use rustc::mir::interpret::GlobalId;
 use rustc::hir;
 use rustc::hir::def::{CtorKind, DefKind, Res};
-use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc::hir::ptr::P;
-use rustc::ty::subst::{InternalSubsts, SubstsRef, GenericArgKind};
-use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
+use rustc::ty::subst::InternalSubsts;
+use rustc::ty::{self, TyCtxt, Ty, AdtKind};
 use rustc::ty::fold::TypeFolder;
-use rustc::ty::layout::VariantIdx;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
-use syntax::ast::{self, Attribute, AttrStyle, AttrKind, Ident};
+use syntax::ast::{self, Ident};
 use syntax::attr;
-use syntax::util::comments;
-use syntax::source_map::DUMMY_SP;
-use syntax_pos::symbol::{Symbol, kw, sym};
+use syntax_pos::symbol::{kw, sym};
 use syntax_pos::hygiene::MacroKind;
-use syntax_pos::{self, Pos, FileName};
+use syntax_pos::{self, Pos};
 
 use std::collections::hash_map::Entry;
-use std::fmt;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
 use std::default::Default;
-use std::{mem, slice, vec};
-use std::num::NonZeroU32;
-use std::iter::FromIterator;
+use std::{mem, vec};
 use std::rc::Rc;
-use std::cell::RefCell;
-use std::sync::Arc;
 use std::u32;
 
 use crate::core::{self, DocContext, ImplTraitParam};
 use crate::doctree;
-use crate::html::render::{cache, ExternalLocation};
-use crate::html::item_type::ItemType;
 
+use utils::*;
 
-use self::cfg::Cfg;
-use self::auto_trait::AutoTraitFinder;
-use self::blanket_impl::BlanketImplFinder;
+pub use utils::{get_auto_trait_and_blanket_impls, krate, register_res};
 
-pub use self::Type::*;
-pub use self::Mutability::*;
-pub use self::ItemEnum::*;
-pub use self::SelfTy::*;
-pub use self::FunctionRetTy::*;
-pub use self::Visibility::{Public, Inherited};
-
-thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
+pub use self::types::*;
+pub use self::types::Type::*;
+pub use self::types::Mutability::*;
+pub use self::types::ItemEnum::*;
+pub use self::types::SelfTy::*;
+pub use self::types::FunctionRetTy::*;
+pub use self::types::Visibility::{Public, Inherited};
 
 const FN_OUTPUT_NAME: &'static str = "Output";
 
-// extract the stability index for a node from tcx, if possible
-fn get_stability(cx: &DocContext<'_>, def_id: DefId) -> Option<Stability> {
-    cx.tcx.lookup_stability(def_id).clean(cx)
-}
-
-fn get_deprecation(cx: &DocContext<'_>, def_id: DefId) -> Option<Deprecation> {
-    cx.tcx.lookup_deprecation(def_id).clean(cx)
-}
-
 pub trait Clean<T> {
     fn clean(&self, cx: &DocContext<'_>) -> T;
 }
@@ -122,115 +100,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Crate {
-    pub name: String,
-    pub version: Option<String>,
-    pub src: FileName,
-    pub module: Option<Item>,
-    pub externs: Vec<(CrateNum, ExternalCrate)>,
-    pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
-    // These are later on moved into `CACHEKEY`, leaving the map empty.
-    // Only here so that they can be filtered through the rustdoc passes.
-    pub external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
-    pub masked_crates: FxHashSet<CrateNum>,
-    pub collapsed: bool,
-}
-
-pub fn krate(mut cx: &mut DocContext<'_>) -> Crate {
-    use crate::visit_lib::LibEmbargoVisitor;
-
-    let krate = cx.tcx.hir().krate();
-    let module = crate::visit_ast::RustdocVisitor::new(&mut cx).visit(krate);
-
-    let mut r = cx.renderinfo.get_mut();
-    r.deref_trait_did = cx.tcx.lang_items().deref_trait();
-    r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
-    r.owned_box_did = cx.tcx.lang_items().owned_box();
-
-    let mut externs = Vec::new();
-    for &cnum in cx.tcx.crates().iter() {
-        externs.push((cnum, cnum.clean(cx)));
-        // Analyze doc-reachability for extern items
-        LibEmbargoVisitor::new(&mut cx).visit_lib(cnum);
-    }
-    externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
-
-    // Clean the crate, translating the entire libsyntax AST to one that is
-    // understood by rustdoc.
-    let mut module = module.clean(cx);
-    let mut masked_crates = FxHashSet::default();
-
-    match module.inner {
-        ModuleItem(ref module) => {
-            for it in &module.items {
-                // `compiler_builtins` should be masked too, but we can't apply
-                // `#[doc(masked)]` to the injected `extern crate` because it's unstable.
-                if it.is_extern_crate()
-                    && (it.attrs.has_doc_flag(sym::masked)
-                        || cx.tcx.is_compiler_builtins(it.def_id.krate))
-                {
-                    masked_crates.insert(it.def_id.krate);
-                }
-            }
-        }
-        _ => unreachable!(),
-    }
-
-    let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
-    {
-        let m = match module.inner {
-            ModuleItem(ref mut m) => m,
-            _ => unreachable!(),
-        };
-        m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| {
-            Item {
-                source: Span::empty(),
-                name: Some(prim.to_url_str().to_string()),
-                attrs: attrs.clone(),
-                visibility: Public,
-                stability: get_stability(cx, def_id),
-                deprecation: get_deprecation(cx, def_id),
-                def_id,
-                inner: PrimitiveItem(prim),
-            }
-        }));
-        m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| {
-            Item {
-                source: Span::empty(),
-                name: Some(kw.clone()),
-                attrs,
-                visibility: Public,
-                stability: get_stability(cx, def_id),
-                deprecation: get_deprecation(cx, def_id),
-                def_id,
-                inner: KeywordItem(kw),
-            }
-        }));
-    }
-
-    Crate {
-        name,
-        version: None,
-        src,
-        module: Some(module),
-        externs,
-        primitives,
-        external_traits: cx.external_traits.clone(),
-        masked_crates,
-        collapsed: false,
-    }
-}
-
-#[derive(Clone, Debug)]
-pub struct ExternalCrate {
-    pub name: String,
-    pub src: FileName,
-    pub attrs: Attributes,
-    pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
-    pub keywords: Vec<(DefId, String, Attributes)>,
-}
-
 impl Clean<ExternalCrate> for CrateNum {
     fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
         let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
@@ -351,237 +220,6 @@
     }
 }
 
-/// Anything with a source location and set of attributes and, optionally, a
-/// name. That is, anything that can be documented. This doesn't correspond
-/// directly to the AST's concept of an item; it's a strict superset.
-#[derive(Clone)]
-pub struct Item {
-    /// Stringified span
-    pub source: Span,
-    /// Not everything has a name. E.g., impls
-    pub name: Option<String>,
-    pub attrs: Attributes,
-    pub inner: ItemEnum,
-    pub visibility: Visibility,
-    pub def_id: DefId,
-    pub stability: Option<Stability>,
-    pub deprecation: Option<Deprecation>,
-}
-
-impl fmt::Debug for Item {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-
-        let fake = MAX_DEF_ID.with(|m| m.borrow().get(&self.def_id.krate)
-                                   .map(|id| self.def_id >= *id).unwrap_or(false));
-        let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
-
-        fmt.debug_struct("Item")
-            .field("source", &self.source)
-            .field("name", &self.name)
-            .field("attrs", &self.attrs)
-            .field("inner", &self.inner)
-            .field("visibility", &self.visibility)
-            .field("def_id", def_id)
-            .field("stability", &self.stability)
-            .field("deprecation", &self.deprecation)
-            .finish()
-    }
-}
-
-impl Item {
-    /// Finds the `doc` attribute as a NameValue and returns the corresponding
-    /// value found.
-    pub fn doc_value(&self) -> Option<&str> {
-        self.attrs.doc_value()
-    }
-    /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
-    /// with newlines.
-    pub fn collapsed_doc_value(&self) -> Option<String> {
-        self.attrs.collapsed_doc_value()
-    }
-
-    pub fn links(&self) -> Vec<(String, String)> {
-        self.attrs.links(&self.def_id.krate)
-    }
-
-    pub fn is_crate(&self) -> bool {
-        match self.inner {
-            StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
-            ModuleItem(Module { is_crate: true, ..}) => true,
-            _ => false,
-        }
-    }
-    pub fn is_mod(&self) -> bool {
-        self.type_() == ItemType::Module
-    }
-    pub fn is_trait(&self) -> bool {
-        self.type_() == ItemType::Trait
-    }
-    pub fn is_struct(&self) -> bool {
-        self.type_() == ItemType::Struct
-    }
-    pub fn is_enum(&self) -> bool {
-        self.type_() == ItemType::Enum
-    }
-    pub fn is_variant(&self) -> bool {
-        self.type_() == ItemType::Variant
-    }
-    pub fn is_associated_type(&self) -> bool {
-        self.type_() == ItemType::AssocType
-    }
-    pub fn is_associated_const(&self) -> bool {
-        self.type_() == ItemType::AssocConst
-    }
-    pub fn is_method(&self) -> bool {
-        self.type_() == ItemType::Method
-    }
-    pub fn is_ty_method(&self) -> bool {
-        self.type_() == ItemType::TyMethod
-    }
-    pub fn is_typedef(&self) -> bool {
-        self.type_() == ItemType::Typedef
-    }
-    pub fn is_primitive(&self) -> bool {
-        self.type_() == ItemType::Primitive
-    }
-    pub fn is_union(&self) -> bool {
-        self.type_() == ItemType::Union
-    }
-    pub fn is_import(&self) -> bool {
-        self.type_() == ItemType::Import
-    }
-    pub fn is_extern_crate(&self) -> bool {
-        self.type_() == ItemType::ExternCrate
-    }
-    pub fn is_keyword(&self) -> bool {
-        self.type_() == ItemType::Keyword
-    }
-
-    pub fn is_stripped(&self) -> bool {
-        match self.inner { StrippedItem(..) => true, _ => false }
-    }
-    pub fn has_stripped_fields(&self) -> Option<bool> {
-        match self.inner {
-            StructItem(ref _struct) => Some(_struct.fields_stripped),
-            UnionItem(ref union) => Some(union.fields_stripped),
-            VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)} ) => {
-                Some(vstruct.fields_stripped)
-            },
-            _ => None,
-        }
-    }
-
-    pub fn stability_class(&self) -> Option<String> {
-        self.stability.as_ref().and_then(|ref s| {
-            let mut classes = Vec::with_capacity(2);
-
-            if s.level == stability::Unstable {
-                classes.push("unstable");
-            }
-
-            if s.deprecation.is_some() {
-                classes.push("deprecated");
-            }
-
-            if classes.len() != 0 {
-                Some(classes.join(" "))
-            } else {
-                None
-            }
-        })
-    }
-
-    pub fn stable_since(&self) -> Option<&str> {
-        self.stability.as_ref().map(|s| &s.since[..])
-    }
-
-    pub fn is_non_exhaustive(&self) -> bool {
-        self.attrs.other_attrs.iter()
-            .any(|a| a.check_name(sym::non_exhaustive))
-    }
-
-    /// Returns a documentation-level item type from the item.
-    pub fn type_(&self) -> ItemType {
-        ItemType::from(self)
-    }
-
-    /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
-    ///
-    /// If the item is not deprecated, returns `None`.
-    pub fn deprecation(&self) -> Option<&Deprecation> {
-        self.deprecation
-            .as_ref()
-            .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref()))
-    }
-    pub fn is_default(&self) -> bool {
-        match self.inner {
-            ItemEnum::MethodItem(ref meth) => {
-                if let Some(defaultness) = meth.defaultness {
-                    defaultness.has_value() && !defaultness.is_final()
-                } else {
-                    false
-                }
-            }
-            _ => false,
-        }
-    }
-}
-
-#[derive(Clone, Debug)]
-pub enum ItemEnum {
-    ExternCrateItem(String, Option<String>),
-    ImportItem(Import),
-    StructItem(Struct),
-    UnionItem(Union),
-    EnumItem(Enum),
-    FunctionItem(Function),
-    ModuleItem(Module),
-    TypedefItem(Typedef, bool /* is associated type */),
-    OpaqueTyItem(OpaqueTy, bool /* is associated type */),
-    StaticItem(Static),
-    ConstantItem(Constant),
-    TraitItem(Trait),
-    TraitAliasItem(TraitAlias),
-    ImplItem(Impl),
-    /// A method signature only. Used for required methods in traits (ie,
-    /// non-default-methods).
-    TyMethodItem(TyMethod),
-    /// A method with a body.
-    MethodItem(Method),
-    StructFieldItem(Type),
-    VariantItem(Variant),
-    /// `fn`s from an extern block
-    ForeignFunctionItem(Function),
-    /// `static`s from an extern block
-    ForeignStaticItem(Static),
-    /// `type`s from an extern block
-    ForeignTypeItem,
-    MacroItem(Macro),
-    ProcMacroItem(ProcMacro),
-    PrimitiveItem(PrimitiveType),
-    AssocConstItem(Type, Option<String>),
-    AssocTypeItem(Vec<GenericBound>, Option<Type>),
-    /// An item that has been stripped by a rustdoc pass
-    StrippedItem(Box<ItemEnum>),
-    KeywordItem(String),
-}
-
-impl ItemEnum {
-    pub fn is_associated(&self) -> bool {
-        match *self {
-            ItemEnum::TypedefItem(_, _) |
-            ItemEnum::AssocTypeItem(_, _) => true,
-            _ => false,
-        }
-    }
-}
-
-#[derive(Clone, Debug)]
-pub struct Module {
-    pub items: Vec<Item>,
-    pub is_crate: bool,
-}
-
 impl Clean<Item> for doctree::Module<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let name = if self.name.is_some() {
@@ -645,465 +283,12 @@
     }
 }
 
-pub struct ListAttributesIter<'a> {
-    attrs: slice::Iter<'a, ast::Attribute>,
-    current_list: vec::IntoIter<ast::NestedMetaItem>,
-    name: Symbol,
-}
-
-impl<'a> Iterator for ListAttributesIter<'a> {
-    type Item = ast::NestedMetaItem;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        if let Some(nested) = self.current_list.next() {
-            return Some(nested);
-        }
-
-        for attr in &mut self.attrs {
-            if let Some(list) = attr.meta_item_list() {
-                if attr.check_name(self.name) {
-                    self.current_list = list.into_iter();
-                    if let Some(nested) = self.current_list.next() {
-                        return Some(nested);
-                    }
-                }
-            }
-        }
-
-        None
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let lower = self.current_list.len();
-        (lower, None)
-    }
-}
-
-pub trait AttributesExt {
-    /// Finds an attribute as List and returns the list of attributes nested inside.
-    fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
-}
-
-impl AttributesExt for [ast::Attribute] {
-    fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
-        ListAttributesIter {
-            attrs: self.iter(),
-            current_list: Vec::new().into_iter(),
-            name,
-        }
-    }
-}
-
-pub trait NestedAttributesExt {
-    /// Returns `true` if the attribute list contains a specific `Word`
-    fn has_word(self, word: Symbol) -> bool;
-}
-
-impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I {
-    fn has_word(self, word: Symbol) -> bool {
-        self.into_iter().any(|attr| attr.is_word() && attr.check_name(word))
-    }
-}
-
-/// A portion of documentation, extracted from a `#[doc]` attribute.
-///
-/// Each variant contains the line number within the complete doc-comment where the fragment
-/// starts, as well as the Span where the corresponding doc comment or attribute is located.
-///
-/// Included files are kept separate from inline doc comments so that proper line-number
-/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
-/// kept separate because of issue #42760.
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum DocFragment {
-    /// A doc fragment created from a `///` or `//!` doc comment.
-    SugaredDoc(usize, syntax_pos::Span, String),
-    /// A doc fragment created from a "raw" `#[doc=""]` attribute.
-    RawDoc(usize, syntax_pos::Span, String),
-    /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
-    /// given filename and the file contents.
-    Include(usize, syntax_pos::Span, String, String),
-}
-
-impl DocFragment {
-    pub fn as_str(&self) -> &str {
-        match *self {
-            DocFragment::SugaredDoc(_, _, ref s) => &s[..],
-            DocFragment::RawDoc(_, _, ref s) => &s[..],
-            DocFragment::Include(_, _, _, ref s) => &s[..],
-        }
-    }
-
-    pub fn span(&self) -> syntax_pos::Span {
-        match *self {
-            DocFragment::SugaredDoc(_, span, _) |
-                DocFragment::RawDoc(_, span, _) |
-                DocFragment::Include(_, span, _, _) => span,
-        }
-    }
-}
-
-impl<'a> FromIterator<&'a DocFragment> for String {
-    fn from_iter<T>(iter: T) -> Self
-    where
-        T: IntoIterator<Item = &'a DocFragment>
-    {
-        iter.into_iter().fold(String::new(), |mut acc, frag| {
-            if !acc.is_empty() {
-                acc.push('\n');
-            }
-            match *frag {
-                DocFragment::SugaredDoc(_, _, ref docs)
-                    | DocFragment::RawDoc(_, _, ref docs)
-                    | DocFragment::Include(_, _, _, ref docs) =>
-                    acc.push_str(docs),
-            }
-
-            acc
-        })
-    }
-}
-
-#[derive(Clone, Debug, Default)]
-pub struct Attributes {
-    pub doc_strings: Vec<DocFragment>,
-    pub other_attrs: Vec<ast::Attribute>,
-    pub cfg: Option<Arc<Cfg>>,
-    pub span: Option<syntax_pos::Span>,
-    /// map from Rust paths to resolved defs and potential URL fragments
-    pub links: Vec<(String, Option<DefId>, Option<String>)>,
-    pub inner_docs: bool,
-}
-
-impl Attributes {
-    /// Extracts the content from an attribute `#[doc(cfg(content))]`.
-    fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
-        use syntax::ast::NestedMetaItem::MetaItem;
-
-        if let ast::MetaItemKind::List(ref nmis) = mi.kind {
-            if nmis.len() == 1 {
-                if let MetaItem(ref cfg_mi) = nmis[0] {
-                    if cfg_mi.check_name(sym::cfg) {
-                        if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
-                            if cfg_nmis.len() == 1 {
-                                if let MetaItem(ref content_mi) = cfg_nmis[0] {
-                                    return Some(content_mi);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        None
-    }
-
-    /// Reads a `MetaItem` from within an attribute, looks for whether it is a
-    /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
-    /// its expansion.
-    fn extract_include(mi: &ast::MetaItem)
-        -> Option<(String, String)>
-    {
-        mi.meta_item_list().and_then(|list| {
-            for meta in list {
-                if meta.check_name(sym::include) {
-                    // the actual compiled `#[doc(include="filename")]` gets expanded to
-                    // `#[doc(include(file="filename", contents="file contents")]` so we need to
-                    // look for that instead
-                    return meta.meta_item_list().and_then(|list| {
-                        let mut filename: Option<String> = None;
-                        let mut contents: Option<String> = None;
-
-                        for it in list {
-                            if it.check_name(sym::file) {
-                                if let Some(name) = it.value_str() {
-                                    filename = Some(name.to_string());
-                                }
-                            } else if it.check_name(sym::contents) {
-                                if let Some(docs) = it.value_str() {
-                                    contents = Some(docs.to_string());
-                                }
-                            }
-                        }
-
-                        if let (Some(filename), Some(contents)) = (filename, contents) {
-                            Some((filename, contents))
-                        } else {
-                            None
-                        }
-                    });
-                }
-            }
-
-            None
-        })
-    }
-
-    pub fn has_doc_flag(&self, flag: Symbol) -> bool {
-        for attr in &self.other_attrs {
-            if !attr.check_name(sym::doc) { continue; }
-
-            if let Some(items) = attr.meta_item_list() {
-                if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) {
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
-
-    pub fn from_ast(diagnostic: &::errors::Handler,
-                    attrs: &[ast::Attribute]) -> Attributes {
-        let mut doc_strings = vec![];
-        let mut sp = None;
-        let mut cfg = Cfg::True;
-        let mut doc_line = 0;
-
-        /// If `attr` is a doc comment, strips the leading and (if present)
-        /// trailing comments symbols, e.g. `///`, `/**`, and `*/`. Otherwise,
-        /// returns `attr` unchanged.
-        pub fn with_doc_comment_markers_stripped<T>(
-            attr: &Attribute,
-            f: impl FnOnce(&Attribute) -> T
-        ) -> T {
-            match attr.kind {
-                AttrKind::Normal(_) => {
-                    f(attr)
-                }
-                AttrKind::DocComment(comment) => {
-                    let comment =
-                        Symbol::intern(&comments::strip_doc_comment_decoration(&comment.as_str()));
-                    f(&Attribute {
-                        kind: AttrKind::DocComment(comment),
-                        id: attr.id,
-                        style: attr.style,
-                        span: attr.span,
-                    })
-                }
-            }
-        }
-
-        let other_attrs = attrs.iter().filter_map(|attr| {
-            with_doc_comment_markers_stripped(attr, |attr| {
-                if attr.check_name(sym::doc) {
-                    if let Some(mi) = attr.meta() {
-                        if let Some(value) = mi.value_str() {
-                            // Extracted #[doc = "..."]
-                            let value = value.to_string();
-                            let line = doc_line;
-                            doc_line += value.lines().count();
-
-                            if attr.is_doc_comment() {
-                                doc_strings.push(DocFragment::SugaredDoc(line, attr.span, value));
-                            } else {
-                                doc_strings.push(DocFragment::RawDoc(line, attr.span, value));
-                            }
-
-                            if sp.is_none() {
-                                sp = Some(attr.span);
-                            }
-                            return None;
-                        } else if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
-                            // Extracted #[doc(cfg(...))]
-                            match Cfg::parse(cfg_mi) {
-                                Ok(new_cfg) => cfg &= new_cfg,
-                                Err(e) => diagnostic.span_err(e.span, e.msg),
-                            }
-                            return None;
-                        } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
-                        {
-                            let line = doc_line;
-                            doc_line += contents.lines().count();
-                            doc_strings.push(DocFragment::Include(line,
-                                                                  attr.span,
-                                                                  filename,
-                                                                  contents));
-                        }
-                    }
-                }
-                Some(attr.clone())
-            })
-        }).collect();
-
-        // treat #[target_feature(enable = "feat")] attributes as if they were
-        // #[doc(cfg(target_feature = "feat"))] attributes as well
-        for attr in attrs.lists(sym::target_feature) {
-            if attr.check_name(sym::enable) {
-                if let Some(feat) = attr.value_str() {
-                    let meta = attr::mk_name_value_item_str(
-                        Ident::with_dummy_span(sym::target_feature), feat, DUMMY_SP
-                    );
-                    if let Ok(feat_cfg) = Cfg::parse(&meta) {
-                        cfg &= feat_cfg;
-                    }
-                }
-            }
-        }
-
-        let inner_docs = attrs.iter()
-                              .filter(|a| a.check_name(sym::doc))
-                              .next()
-                              .map_or(true, |a| a.style == AttrStyle::Inner);
-
-        Attributes {
-            doc_strings,
-            other_attrs,
-            cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
-            span: sp,
-            links: vec![],
-            inner_docs,
-        }
-    }
-
-    /// Finds the `doc` attribute as a NameValue and returns the corresponding
-    /// value found.
-    pub fn doc_value(&self) -> Option<&str> {
-        self.doc_strings.first().map(|s| s.as_str())
-    }
-
-    /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
-    /// with newlines.
-    pub fn collapsed_doc_value(&self) -> Option<String> {
-        if !self.doc_strings.is_empty() {
-            Some(self.doc_strings.iter().collect())
-        } else {
-            None
-        }
-    }
-
-    /// Gets links as a vector
-    ///
-    /// Cache must be populated before call
-    pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
-        use crate::html::format::href;
-
-        self.links.iter().filter_map(|&(ref s, did, ref fragment)| {
-            match did {
-                Some(did) => {
-                    if let Some((mut href, ..)) = href(did) {
-                        if let Some(ref fragment) = *fragment {
-                            href.push_str("#");
-                            href.push_str(fragment);
-                        }
-                        Some((s.clone(), href))
-                    } else {
-                        None
-                    }
-                }
-                None => {
-                    if let Some(ref fragment) = *fragment {
-                        let cache = cache();
-                        let url = match cache.extern_locations.get(krate) {
-                            Some(&(_, ref src, ExternalLocation::Local)) =>
-                                src.to_str().expect("invalid file path"),
-                            Some(&(_, _, ExternalLocation::Remote(ref s))) => s,
-                            Some(&(_, _, ExternalLocation::Unknown)) | None =>
-                                "https://doc.rust-lang.org/nightly",
-                        };
-                        // This is a primitive so the url is done "by hand".
-                        let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
-                        Some((s.clone(),
-                              format!("{}{}std/primitive.{}.html{}",
-                                      url,
-                                      if !url.ends_with('/') { "/" } else { "" },
-                                      &fragment[..tail],
-                                      &fragment[tail..])))
-                    } else {
-                        panic!("This isn't a primitive?!");
-                    }
-                }
-            }
-        }).collect()
-    }
-}
-
-impl PartialEq for Attributes {
-    fn eq(&self, rhs: &Self) -> bool {
-        self.doc_strings == rhs.doc_strings &&
-        self.cfg == rhs.cfg &&
-        self.span == rhs.span &&
-        self.links == rhs.links &&
-        self.other_attrs.iter().map(|attr| attr.id).eq(rhs.other_attrs.iter().map(|attr| attr.id))
-    }
-}
-
-impl Eq for Attributes {}
-
-impl Hash for Attributes {
-    fn hash<H: Hasher>(&self, hasher: &mut H) {
-        self.doc_strings.hash(hasher);
-        self.cfg.hash(hasher);
-        self.span.hash(hasher);
-        self.links.hash(hasher);
-        for attr in &self.other_attrs {
-            attr.id.hash(hasher);
-        }
-    }
-}
-
-impl AttributesExt for Attributes {
-    fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
-        self.other_attrs.lists(name)
-    }
-}
-
 impl Clean<Attributes> for [ast::Attribute] {
     fn clean(&self, cx: &DocContext<'_>) -> Attributes {
         Attributes::from_ast(cx.sess().diagnostic(), self)
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum GenericBound {
-    TraitBound(PolyTrait, hir::TraitBoundModifier),
-    Outlives(Lifetime),
-}
-
-impl GenericBound {
-    fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
-        let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
-        let empty = cx.tcx.intern_substs(&[]);
-        let path = external_path(cx, cx.tcx.item_name(did),
-            Some(did), false, vec![], empty);
-        inline::record_extern_fqn(cx, did, TypeKind::Trait);
-        GenericBound::TraitBound(PolyTrait {
-            trait_: ResolvedPath {
-                path,
-                param_names: None,
-                did,
-                is_generic: false,
-            },
-            generic_params: Vec::new(),
-        }, hir::TraitBoundModifier::Maybe)
-    }
-
-    fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
-        use rustc::hir::TraitBoundModifier as TBM;
-        if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
-            if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
-                return true;
-            }
-        }
-        false
-    }
-
-    fn get_poly_trait(&self) -> Option<PolyTrait> {
-        if let GenericBound::TraitBound(ref p, _) = *self {
-            return Some(p.clone())
-        }
-        None
-    }
-
-    fn get_trait_type(&self) -> Option<Type> {
-        if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
-            Some(trait_.clone())
-        } else {
-            None
-        }
-    }
-}
-
 impl Clean<GenericBound> for hir::GenericBound {
     fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
         match *self {
@@ -1115,66 +300,6 @@
     }
 }
 
-fn external_generic_args(
-    cx: &DocContext<'_>,
-    trait_did: Option<DefId>,
-    has_self: bool,
-    bindings: Vec<TypeBinding>,
-    substs: SubstsRef<'_>,
-) -> GenericArgs {
-    let mut skip_self = has_self;
-    let mut ty_kind = None;
-    let args: Vec<_> = substs.iter().filter_map(|kind| match kind.unpack() {
-        GenericArgKind::Lifetime(lt) => {
-            lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt)))
-        }
-        GenericArgKind::Type(_) if skip_self => {
-            skip_self = false;
-            None
-        }
-        GenericArgKind::Type(ty) => {
-            ty_kind = Some(&ty.kind);
-            Some(GenericArg::Type(ty.clean(cx)))
-        }
-        GenericArgKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
-    }).collect();
-
-    match trait_did {
-        // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
-        Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
-            assert!(ty_kind.is_some());
-            let inputs = match ty_kind {
-                Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
-                _ => return GenericArgs::AngleBracketed { args, bindings },
-            };
-            let output = None;
-            // FIXME(#20299) return type comes from a projection now
-            // match types[1].kind {
-            //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
-            //     _ => Some(types[1].clean(cx))
-            // };
-            GenericArgs::Parenthesized { inputs, output }
-        },
-        _ => {
-            GenericArgs::AngleBracketed { args, bindings }
-        }
-    }
-}
-
-// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
-// from Fn<(A, B,), C> to Fn(A, B) -> C
-fn external_path(cx: &DocContext<'_>, name: Symbol, trait_did: Option<DefId>, has_self: bool,
-                 bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> Path {
-    Path {
-        global: false,
-        res: Res::Err,
-        segments: vec![PathSegment {
-            name: name.to_string(),
-            args: external_generic_args(cx, trait_did, has_self, bindings, substs)
-        }],
-    }
-}
-
 impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
     fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
         let (trait_ref, ref bounds) = *self;
@@ -1237,21 +362,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct Lifetime(String);
-
-impl Lifetime {
-    pub fn get_ref<'a>(&'a self) -> &'a str {
-        let Lifetime(ref s) = *self;
-        let s: &'a str = s;
-        s
-    }
-
-    pub fn statik() -> Lifetime {
-        Lifetime("'static".to_string())
-    }
-}
-
 impl Clean<Lifetime> for hir::Lifetime {
     fn clean(&self, cx: &DocContext<'_>) -> Lifetime {
         if self.hir_id != hir::DUMMY_HIR_ID {
@@ -1332,23 +442,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub enum WherePredicate {
-    BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
-    RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
-    EqPredicate { lhs: Type, rhs: Type },
-}
-
-impl WherePredicate {
-    pub fn get_bounds(&self) -> Option<&[GenericBound]> {
-        match *self {
-            WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
-            WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
-            _ => None,
-        }
-    }
-}
-
 impl Clean<WherePredicate> for hir::WherePredicate {
     fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
         match *self {
@@ -1470,73 +563,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum GenericParamDefKind {
-    Lifetime,
-    Type {
-        did: DefId,
-        bounds: Vec<GenericBound>,
-        default: Option<Type>,
-        synthetic: Option<hir::SyntheticTyParamKind>,
-    },
-    Const {
-        did: DefId,
-        ty: Type,
-    },
-}
-
-impl GenericParamDefKind {
-    pub fn is_type(&self) -> bool {
-        match *self {
-            GenericParamDefKind::Type { .. } => true,
-            _ => false,
-        }
-    }
-
-    // FIXME(eddyb) this either returns the default of a type parameter, or the
-    // type of a `const` parameter. It seems that the intention is to *visit*
-    // any embedded types, but `get_type` seems to be the wrong name for that.
-    pub fn get_type(&self) -> Option<Type> {
-        match self {
-            GenericParamDefKind::Type { default, .. } => default.clone(),
-            GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
-            GenericParamDefKind::Lifetime => None,
-        }
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct GenericParamDef {
-    pub name: String,
-
-    pub kind: GenericParamDefKind,
-}
-
-impl GenericParamDef {
-    pub fn is_synthetic_type_param(&self) -> bool {
-        match self.kind {
-            GenericParamDefKind::Lifetime |
-            GenericParamDefKind::Const { .. } => false,
-            GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
-        }
-    }
-
-    pub fn is_type(&self) -> bool {
-        self.kind.is_type()
-    }
-
-    pub fn get_type(&self) -> Option<Type> {
-        self.kind.get_type()
-    }
-
-    pub fn get_bounds(&self) -> Option<&[GenericBound]> {
-        match self.kind {
-            GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
-            _ => None,
-        }
-    }
-}
-
 impl Clean<GenericParamDef> for ty::GenericParamDef {
     fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
         let (name, kind) = match self.kind {
@@ -1614,13 +640,6 @@
     }
 }
 
-// maybe use a Generic enum and use Vec<Generic>?
-#[derive(Clone, Debug, Default)]
-pub struct Generics {
-    pub params: Vec<GenericParamDef>,
-    pub where_predicates: Vec<WherePredicate>,
-}
-
 impl Clean<Generics> for hir::Generics {
     fn clean(&self, cx: &DocContext<'_>) -> Generics {
         // Synthetic type-parameters are inserted after normal ones.
@@ -1863,128 +882,6 @@
     }
 }
 
-/// The point of this function is to replace bounds with types.
-///
-/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
-/// `[Display, Option]` (we just returns the list of the types, we don't care about the
-/// wrapped types in here).
-fn get_real_types(
-    generics: &Generics,
-    arg: &Type,
-    cx: &DocContext<'_>,
-    recurse: i32,
-) -> FxHashSet<Type> {
-    let arg_s = arg.print().to_string();
-    let mut res = FxHashSet::default();
-    if recurse >= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed
-        return res;
-    }
-    if arg.is_full_generic() {
-        if let Some(where_pred) = generics.where_predicates.iter().find(|g| {
-            match g {
-                &WherePredicate::BoundPredicate { ref ty, .. } => ty.def_id() == arg.def_id(),
-                _ => false,
-            }
-        }) {
-            let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
-            for bound in bounds.iter() {
-                match *bound {
-                    GenericBound::TraitBound(ref poly_trait, _) => {
-                        for x in poly_trait.generic_params.iter() {
-                            if !x.is_type() {
-                                continue
-                            }
-                            if let Some(ty) = x.get_type() {
-                                let adds = get_real_types(generics, &ty, cx, recurse + 1);
-                                if !adds.is_empty() {
-                                    res.extend(adds);
-                                } else if !ty.is_full_generic() {
-                                    res.insert(ty);
-                                }
-                            }
-                        }
-                    }
-                    _ => {}
-                }
-            }
-        }
-        if let Some(bound) = generics.params.iter().find(|g| {
-            g.is_type() && g.name == arg_s
-        }) {
-            for bound in bound.get_bounds().unwrap_or_else(|| &[]) {
-                if let Some(ty) = bound.get_trait_type() {
-                    let adds = get_real_types(generics, &ty, cx, recurse + 1);
-                    if !adds.is_empty() {
-                        res.extend(adds);
-                    } else if !ty.is_full_generic() {
-                        res.insert(ty.clone());
-                    }
-                }
-            }
-        }
-    } else {
-        res.insert(arg.clone());
-        if let Some(gens) = arg.generics() {
-            for gen in gens.iter() {
-                if gen.is_full_generic() {
-                    let adds = get_real_types(generics, gen, cx, recurse + 1);
-                    if !adds.is_empty() {
-                        res.extend(adds);
-                    }
-                } else {
-                    res.insert(gen.clone());
-                }
-            }
-        }
-    }
-    res
-}
-
-/// Return the full list of types when bounds have been resolved.
-///
-/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
-/// `[u32, Display, Option]`.
-pub fn get_all_types(
-    generics: &Generics,
-    decl: &FnDecl,
-    cx: &DocContext<'_>,
-) -> (Vec<Type>, Vec<Type>) {
-    let mut all_types = FxHashSet::default();
-    for arg in decl.inputs.values.iter() {
-        if arg.type_.is_self_type() {
-            continue;
-        }
-        let args = get_real_types(generics, &arg.type_, cx, 0);
-        if !args.is_empty() {
-            all_types.extend(args);
-        } else {
-            all_types.insert(arg.type_.clone());
-        }
-    }
-
-    let ret_types = match decl.output {
-        FunctionRetTy::Return(ref return_type) => {
-            let mut ret = get_real_types(generics, &return_type, cx, 0);
-            if ret.is_empty() {
-                ret.insert(return_type.clone());
-            }
-            ret.into_iter().collect()
-        }
-        _ => Vec::new(),
-    };
-    (all_types.into_iter().collect(), ret_types)
-}
-
-#[derive(Clone, Debug)]
-pub struct Method {
-    pub generics: Generics,
-    pub decl: FnDecl,
-    pub header: hir::FnHeader,
-    pub defaultness: Option<hir::Defaultness>,
-    pub all_types: Vec<Type>,
-    pub ret_types: Vec<Type>,
-}
-
 impl<'a> Clean<Method> for (&'a hir::FnSig, &'a hir::Generics, hir::BodyId,
                             Option<hir::Defaultness>) {
     fn clean(&self, cx: &DocContext<'_>) -> Method {
@@ -2003,24 +900,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct TyMethod {
-    pub header: hir::FnHeader,
-    pub decl: FnDecl,
-    pub generics: Generics,
-    pub all_types: Vec<Type>,
-    pub ret_types: Vec<Type>,
-}
-
-#[derive(Clone, Debug)]
-pub struct Function {
-    pub decl: FnDecl,
-    pub generics: Generics,
-    pub header: hir::FnHeader,
-    pub all_types: Vec<Type>,
-    pub ret_types: Vec<Type>,
-}
-
 impl Clean<Item> for doctree::Function<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let (generics, decl) = enter_impl_trait(cx, || {
@@ -2053,49 +932,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct FnDecl {
-    pub inputs: Arguments,
-    pub output: FunctionRetTy,
-    pub c_variadic: bool,
-    pub attrs: Attributes,
-}
-
-impl FnDecl {
-    pub fn self_type(&self) -> Option<SelfTy> {
-        self.inputs.values.get(0).and_then(|v| v.to_self())
-    }
-
-    /// Returns the sugared return type for an async function.
-    ///
-    /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
-    /// will return `i32`.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the return type does not match the expected sugaring for async
-    /// functions.
-    pub fn sugared_async_return_type(&self) -> FunctionRetTy {
-        match &self.output {
-            FunctionRetTy::Return(Type::ImplTrait(bounds)) => {
-                match &bounds[0] {
-                    GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
-                        let bindings = trait_.bindings().unwrap();
-                        FunctionRetTy::Return(bindings[0].ty().clone())
-                    }
-                    _ => panic!("unexpected desugaring of async function"),
-                }
-            }
-            _ => panic!("unexpected desugaring of async function"),
-        }
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct Arguments {
-    pub values: Vec<Argument>,
-}
-
 impl<'a> Clean<Arguments> for (&'a [hir::Ty], &'a [ast::Ident]) {
     fn clean(&self, cx: &DocContext<'_>) -> Arguments {
         Arguments {
@@ -2167,42 +1003,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct Argument {
-    pub type_: Type,
-    pub name: String,
-}
-
-#[derive(Clone, PartialEq, Debug)]
-pub enum SelfTy {
-    SelfValue,
-    SelfBorrowed(Option<Lifetime>, Mutability),
-    SelfExplicit(Type),
-}
-
-impl Argument {
-    pub fn to_self(&self) -> Option<SelfTy> {
-        if self.name != "self" {
-            return None;
-        }
-        if self.type_.is_self_type() {
-            return Some(SelfValue);
-        }
-        match self.type_ {
-            BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => {
-                Some(SelfBorrowed(lifetime.clone(), mutability))
-            }
-            _ => Some(SelfExplicit(self.type_.clone()))
-        }
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum FunctionRetTy {
-    Return(Type),
-    DefaultReturn,
-}
-
 impl Clean<FunctionRetTy> for hir::FunctionRetTy {
     fn clean(&self, cx: &DocContext<'_>) -> FunctionRetTy {
         match *self {
@@ -2212,26 +1012,6 @@
     }
 }
 
-impl GetDefId for FunctionRetTy {
-    fn def_id(&self) -> Option<DefId> {
-        match *self {
-            Return(ref ty) => ty.def_id(),
-            DefaultReturn => None,
-        }
-    }
-}
-
-#[derive(Clone, Debug)]
-pub struct Trait {
-    pub auto: bool,
-    pub unsafety: hir::Unsafety,
-    pub items: Vec<Item>,
-    pub generics: Generics,
-    pub bounds: Vec<GenericBound>,
-    pub is_spotlight: bool,
-    pub is_auto: bool,
-}
-
 impl Clean<Item> for doctree::Trait<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let attrs = self.attrs.clean(cx);
@@ -2257,12 +1037,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct TraitAlias {
-    pub generics: Generics,
-    pub bounds: Vec<GenericBound>,
-}
-
 impl Clean<Item> for doctree::TraitAlias<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let attrs = self.attrs.clean(cx);
@@ -2541,321 +1315,6 @@
     }
 }
 
-/// A trait reference, which may have higher ranked lifetimes.
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct PolyTrait {
-    pub trait_: Type,
-    pub generic_params: Vec<GenericParamDef>,
-}
-
-/// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
-/// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
-/// importantly, it does not preserve mutability or boxes.
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum Type {
-    /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
-    ResolvedPath {
-        path: Path,
-        param_names: Option<Vec<GenericBound>>,
-        did: DefId,
-        /// `true` if is a `T::Name` path for associated types.
-        is_generic: bool,
-    },
-    /// For parameterized types, so the consumer of the JSON don't go
-    /// looking for types which don't exist anywhere.
-    Generic(String),
-    /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
-    /// arrays, slices, and tuples.
-    Primitive(PrimitiveType),
-    /// `extern "ABI" fn`
-    BareFunction(Box<BareFunctionDecl>),
-    Tuple(Vec<Type>),
-    Slice(Box<Type>),
-    Array(Box<Type>, String),
-    Never,
-    RawPointer(Mutability, Box<Type>),
-    BorrowedRef {
-        lifetime: Option<Lifetime>,
-        mutability: Mutability,
-        type_: Box<Type>,
-    },
-
-    // `<Type as Trait>::Name`
-    QPath {
-        name: String,
-        self_type: Box<Type>,
-        trait_: Box<Type>
-    },
-
-    // `_`
-    Infer,
-
-    // `impl TraitA + TraitB + ...`
-    ImplTrait(Vec<GenericBound>),
-}
-
-#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
-pub enum PrimitiveType {
-    Isize, I8, I16, I32, I64, I128,
-    Usize, U8, U16, U32, U64, U128,
-    F32, F64,
-    Char,
-    Bool,
-    Str,
-    Slice,
-    Array,
-    Tuple,
-    Unit,
-    RawPointer,
-    Reference,
-    Fn,
-    Never,
-}
-
-#[derive(Clone, Copy, Debug)]
-pub enum TypeKind {
-    Enum,
-    Function,
-    Module,
-    Const,
-    Static,
-    Struct,
-    Union,
-    Trait,
-    Typedef,
-    Foreign,
-    Macro,
-    Attr,
-    Derive,
-    TraitAlias,
-}
-
-pub trait GetDefId {
-    fn def_id(&self) -> Option<DefId>;
-}
-
-impl<T: GetDefId> GetDefId for Option<T> {
-    fn def_id(&self) -> Option<DefId> {
-        self.as_ref().and_then(|d| d.def_id())
-    }
-}
-
-impl Type {
-    pub fn primitive_type(&self) -> Option<PrimitiveType> {
-        match *self {
-            Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
-            Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
-            Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
-            Tuple(ref tys) => if tys.is_empty() {
-                Some(PrimitiveType::Unit)
-            } else {
-                Some(PrimitiveType::Tuple)
-            },
-            RawPointer(..) => Some(PrimitiveType::RawPointer),
-            BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
-            BareFunction(..) => Some(PrimitiveType::Fn),
-            Never => Some(PrimitiveType::Never),
-            _ => None,
-        }
-    }
-
-    pub fn is_generic(&self) -> bool {
-        match *self {
-            ResolvedPath { is_generic, .. } => is_generic,
-            _ => false,
-        }
-    }
-
-    pub fn is_self_type(&self) -> bool {
-        match *self {
-            Generic(ref name) => name == "Self",
-            _ => false
-        }
-    }
-
-    pub fn generics(&self) -> Option<Vec<Type>> {
-        match *self {
-            ResolvedPath { ref path, .. } => {
-                path.segments.last().and_then(|seg| {
-                    if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
-                        Some(args.iter().filter_map(|arg| match arg {
-                            GenericArg::Type(ty) => Some(ty.clone()),
-                            _ => None,
-                        }).collect())
-                    } else {
-                        None
-                    }
-                })
-            }
-            _ => None,
-        }
-    }
-
-    pub fn bindings(&self) -> Option<&[TypeBinding]> {
-        match *self {
-            ResolvedPath { ref path, .. } => {
-                path.segments.last().and_then(|seg| {
-                    if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
-                        Some(&**bindings)
-                    } else {
-                        None
-                    }
-                })
-            }
-            _ => None
-        }
-    }
-
-    pub fn is_full_generic(&self) -> bool {
-        match *self {
-            Type::Generic(_) => true,
-            _ => false,
-        }
-    }
-
-    pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
-        let (self_, trait_, name) = match self {
-            QPath { ref self_type, ref trait_, ref name } => {
-                (self_type, trait_, name)
-            }
-            _ => return None,
-        };
-        let trait_did = match **trait_ {
-            ResolvedPath { did, .. } => did,
-            _ => return None,
-        };
-        Some((&self_, trait_did, name))
-    }
-
-}
-
-impl GetDefId for Type {
-    fn def_id(&self) -> Option<DefId> {
-        match *self {
-            ResolvedPath { did, .. } => Some(did),
-            Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
-            BorrowedRef { type_: box Generic(..), .. } =>
-                Primitive(PrimitiveType::Reference).def_id(),
-            BorrowedRef { ref type_, .. } => type_.def_id(),
-            Tuple(ref tys) => if tys.is_empty() {
-                Primitive(PrimitiveType::Unit).def_id()
-            } else {
-                Primitive(PrimitiveType::Tuple).def_id()
-            },
-            BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
-            Never => Primitive(PrimitiveType::Never).def_id(),
-            Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
-            Array(..) => Primitive(PrimitiveType::Array).def_id(),
-            RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
-            QPath { ref self_type, .. } => self_type.def_id(),
-            _ => None,
-        }
-    }
-}
-
-impl PrimitiveType {
-    fn from_str(s: &str) -> Option<PrimitiveType> {
-        match s {
-            "isize" => Some(PrimitiveType::Isize),
-            "i8" => Some(PrimitiveType::I8),
-            "i16" => Some(PrimitiveType::I16),
-            "i32" => Some(PrimitiveType::I32),
-            "i64" => Some(PrimitiveType::I64),
-            "i128" => Some(PrimitiveType::I128),
-            "usize" => Some(PrimitiveType::Usize),
-            "u8" => Some(PrimitiveType::U8),
-            "u16" => Some(PrimitiveType::U16),
-            "u32" => Some(PrimitiveType::U32),
-            "u64" => Some(PrimitiveType::U64),
-            "u128" => Some(PrimitiveType::U128),
-            "bool" => Some(PrimitiveType::Bool),
-            "char" => Some(PrimitiveType::Char),
-            "str" => Some(PrimitiveType::Str),
-            "f32" => Some(PrimitiveType::F32),
-            "f64" => Some(PrimitiveType::F64),
-            "array" => Some(PrimitiveType::Array),
-            "slice" => Some(PrimitiveType::Slice),
-            "tuple" => Some(PrimitiveType::Tuple),
-            "unit" => Some(PrimitiveType::Unit),
-            "pointer" => Some(PrimitiveType::RawPointer),
-            "reference" => Some(PrimitiveType::Reference),
-            "fn" => Some(PrimitiveType::Fn),
-            "never" => Some(PrimitiveType::Never),
-            _ => None,
-        }
-    }
-
-    pub fn as_str(&self) -> &'static str {
-        use self::PrimitiveType::*;
-        match *self {
-            Isize => "isize",
-            I8 => "i8",
-            I16 => "i16",
-            I32 => "i32",
-            I64 => "i64",
-            I128 => "i128",
-            Usize => "usize",
-            U8 => "u8",
-            U16 => "u16",
-            U32 => "u32",
-            U64 => "u64",
-            U128 => "u128",
-            F32 => "f32",
-            F64 => "f64",
-            Str => "str",
-            Bool => "bool",
-            Char => "char",
-            Array => "array",
-            Slice => "slice",
-            Tuple => "tuple",
-            Unit => "unit",
-            RawPointer => "pointer",
-            Reference => "reference",
-            Fn => "fn",
-            Never => "never",
-        }
-    }
-
-    pub fn to_url_str(&self) -> &'static str {
-        self.as_str()
-    }
-}
-
-impl From<ast::IntTy> for PrimitiveType {
-    fn from(int_ty: ast::IntTy) -> PrimitiveType {
-        match int_ty {
-            ast::IntTy::Isize => PrimitiveType::Isize,
-            ast::IntTy::I8 => PrimitiveType::I8,
-            ast::IntTy::I16 => PrimitiveType::I16,
-            ast::IntTy::I32 => PrimitiveType::I32,
-            ast::IntTy::I64 => PrimitiveType::I64,
-            ast::IntTy::I128 => PrimitiveType::I128,
-        }
-    }
-}
-
-impl From<ast::UintTy> for PrimitiveType {
-    fn from(uint_ty: ast::UintTy) -> PrimitiveType {
-        match uint_ty {
-            ast::UintTy::Usize => PrimitiveType::Usize,
-            ast::UintTy::U8 => PrimitiveType::U8,
-            ast::UintTy::U16 => PrimitiveType::U16,
-            ast::UintTy::U32 => PrimitiveType::U32,
-            ast::UintTy::U64 => PrimitiveType::U64,
-            ast::UintTy::U128 => PrimitiveType::U128,
-        }
-    }
-}
-
-impl From<ast::FloatTy> for PrimitiveType {
-    fn from(float_ty: ast::FloatTy) -> PrimitiveType {
-        match float_ty {
-            ast::FloatTy::F32 => PrimitiveType::F32,
-            ast::FloatTy::F64 => PrimitiveType::F64,
-        }
-    }
-}
-
 impl Clean<Type> for hir::Ty {
     fn clean(&self, cx: &DocContext<'_>) -> Type {
         use rustc::hir::*;
@@ -3310,14 +1769,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub enum Visibility {
-    Public,
-    Inherited,
-    Crate,
-    Restricted(DefId, Path),
-}
-
 impl Clean<Visibility> for hir::Visibility {
     fn clean(&self, cx: &DocContext<'_>) -> Visibility {
         match self.node {
@@ -3339,22 +1790,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Struct {
-    pub struct_type: doctree::StructType,
-    pub generics: Generics,
-    pub fields: Vec<Item>,
-    pub fields_stripped: bool,
-}
-
-#[derive(Clone, Debug)]
-pub struct Union {
-    pub struct_type: doctree::StructType,
-    pub generics: Generics,
-    pub fields: Vec<Item>,
-    pub fields_stripped: bool,
-}
-
 impl Clean<Item> for doctree::Struct<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
@@ -3395,16 +1830,6 @@
     }
 }
 
-/// This is a more limited form of the standard Struct, different in that
-/// it lacks the things most items have (name, id, parameterization). Found
-/// only as a variant in an enum.
-#[derive(Clone, Debug)]
-pub struct VariantStruct {
-    pub struct_type: doctree::StructType,
-    pub fields: Vec<Item>,
-    pub fields_stripped: bool,
-}
-
 impl Clean<VariantStruct> for ::rustc::hir::VariantData {
     fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
         VariantStruct {
@@ -3415,13 +1840,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Enum {
-    pub variants: IndexVec<VariantIdx, Item>,
-    pub generics: Generics,
-    pub variants_stripped: bool,
-}
-
 impl Clean<Item> for doctree::Enum<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
@@ -3441,11 +1859,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Variant {
-    pub kind: VariantKind,
-}
-
 impl Clean<Item> for doctree::Variant<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
@@ -3504,13 +1917,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub enum VariantKind {
-    CLike,
-    Tuple(Vec<Type>),
-    Struct(VariantStruct),
-}
-
 impl Clean<VariantKind> for hir::VariantData {
     fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
         match self {
@@ -3522,31 +1928,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Span {
-    pub filename: FileName,
-    pub loline: usize,
-    pub locol: usize,
-    pub hiline: usize,
-    pub hicol: usize,
-    pub original: syntax_pos::Span,
-}
-
-impl Span {
-    pub fn empty() -> Span {
-        Span {
-            filename: FileName::Anon(0),
-            loline: 0, locol: 0,
-            hiline: 0, hicol: 0,
-            original: syntax_pos::DUMMY_SP,
-        }
-    }
-
-    pub fn span(&self) -> syntax_pos::Span {
-        self.original
-    }
-}
-
 impl Clean<Span> for syntax_pos::Span {
     fn clean(&self, cx: &DocContext<'_>) -> Span {
         if self.is_dummy() {
@@ -3568,19 +1949,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct Path {
-    pub global: bool,
-    pub res: Res,
-    pub segments: Vec<PathSegment>,
-}
-
-impl Path {
-    pub fn last_name(&self) -> &str {
-        self.segments.last().expect("segments were empty").name.as_str()
-    }
-}
-
 impl Clean<Path> for hir::Path {
     fn clean(&self, cx: &DocContext<'_>) -> Path {
         Path {
@@ -3591,25 +1959,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum GenericArg {
-    Lifetime(Lifetime),
-    Type(Type),
-    Const(Constant),
-}
-
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum GenericArgs {
-    AngleBracketed {
-        args: Vec<GenericArg>,
-        bindings: Vec<TypeBinding>,
-    },
-    Parenthesized {
-        inputs: Vec<Type>,
-        output: Option<Type>,
-    }
-}
-
 impl Clean<GenericArgs> for hir::GenericArgs {
     fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
         if self.parenthesized {
@@ -3638,12 +1987,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct PathSegment {
-    pub name: String,
-    pub args: GenericArgs,
-}
-
 impl Clean<PathSegment> for hir::PathSegment {
     fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
         PathSegment {
@@ -3653,66 +1996,6 @@
     }
 }
 
-fn strip_type(ty: Type) -> Type {
-    match ty {
-        Type::ResolvedPath { path, param_names, did, is_generic } => {
-            Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
-        }
-        Type::Tuple(inner_tys) => {
-            Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
-        }
-        Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))),
-        Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s),
-        Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))),
-        Type::BorrowedRef { lifetime, mutability, type_ } => {
-            Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
-        }
-        Type::QPath { name, self_type, trait_ } => {
-            Type::QPath {
-                name,
-                self_type: Box::new(strip_type(*self_type)), trait_: Box::new(strip_type(*trait_))
-            }
-        }
-        _ => ty
-    }
-}
-
-fn strip_path(path: &Path) -> Path {
-    let segments = path.segments.iter().map(|s| {
-        PathSegment {
-            name: s.name.clone(),
-            args: GenericArgs::AngleBracketed {
-                args: vec![],
-                bindings: vec![],
-            }
-        }
-    }).collect();
-
-    Path {
-        global: path.global,
-        res: path.res.clone(),
-        segments,
-    }
-}
-
-fn qpath_to_string(p: &hir::QPath) -> String {
-    let segments = match *p {
-        hir::QPath::Resolved(_, ref path) => &path.segments,
-        hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(),
-    };
-
-    let mut s = String::new();
-    for (i, seg) in segments.iter().enumerate() {
-        if i > 0 {
-            s.push_str("::");
-        }
-        if seg.ident.name != kw::PathRoot {
-            s.push_str(&seg.ident.as_str());
-        }
-    }
-    s
-}
-
 impl Clean<String> for Ident {
     #[inline]
     fn clean(&self, cx: &DocContext<'_>) -> String {
@@ -3727,12 +2010,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Typedef {
-    pub type_: Type,
-    pub generics: Generics,
-}
-
 impl Clean<Item> for doctree::Typedef<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
@@ -3751,12 +2028,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct OpaqueTy {
-    pub bounds: Vec<GenericBound>,
-    pub generics: Generics,
-}
-
 impl Clean<Item> for doctree::OpaqueTy<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
@@ -3775,14 +2046,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct BareFunctionDecl {
-    pub unsafety: hir::Unsafety,
-    pub generic_params: Vec<GenericParamDef>,
-    pub decl: FnDecl,
-    pub abi: Abi,
-}
-
 impl Clean<BareFunctionDecl> for hir::BareFnTy {
     fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
         let (generic_params, decl) = enter_impl_trait(cx, || {
@@ -3797,16 +2060,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Static {
-    pub type_: Type,
-    pub mutability: Mutability,
-    /// It's useful to have the value of a static documented, but I have no
-    /// desire to represent expressions (that'd basically be all of the AST,
-    /// which is huge!). So, have a string.
-    pub expr: String,
-}
-
 impl Clean<Item> for doctree::Static<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
@@ -3827,12 +2080,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub struct Constant {
-    pub type_: Type,
-    pub expr: String,
-}
-
 impl Clean<Item> for doctree::Constant<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
@@ -3851,12 +2098,6 @@
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
-pub enum Mutability {
-    Mutable,
-    Immutable,
-}
-
 impl Clean<Mutability> for hir::Mutability {
     fn clean(&self, _: &DocContext<'_>) -> Mutability {
         match self {
@@ -3866,12 +2107,6 @@
     }
 }
 
-#[derive(Clone, PartialEq, Debug)]
-pub enum ImplPolarity {
-    Positive,
-    Negative,
-}
-
 impl Clean<ImplPolarity> for ty::ImplPolarity {
     fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
         match self {
@@ -3883,28 +2118,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Impl {
-    pub unsafety: hir::Unsafety,
-    pub generics: Generics,
-    pub provided_trait_methods: FxHashSet<String>,
-    pub trait_: Option<Type>,
-    pub for_: Type,
-    pub items: Vec<Item>,
-    pub polarity: Option<ImplPolarity>,
-    pub synthetic: bool,
-    pub blanket_impl: Option<Type>,
-}
-
-pub fn get_auto_trait_and_blanket_impls(
-    cx: &DocContext<'tcx>,
-    ty: Ty<'tcx>,
-    param_env_def_id: DefId,
-) -> impl Iterator<Item = Item> {
-    AutoTraitFinder::new(cx).get_auto_trait_impls(ty, param_env_def_id).into_iter()
-        .chain(BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id))
-}
-
 impl Clean<Vec<Item>> for doctree::Impl<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
         let mut ret = Vec::new();
@@ -3949,63 +2162,6 @@
     }
 }
 
-fn build_deref_target_impls(cx: &DocContext<'_>,
-                            items: &[Item],
-                            ret: &mut Vec<Item>) {
-    use self::PrimitiveType::*;
-    let tcx = cx.tcx;
-
-    for item in items {
-        let target = match item.inner {
-            TypedefItem(ref t, true) => &t.type_,
-            _ => continue,
-        };
-        let primitive = match *target {
-            ResolvedPath { did, .. } if did.is_local() => continue,
-            ResolvedPath { did, .. } => {
-                ret.extend(inline::build_impls(cx, did, None));
-                continue
-            }
-            _ => match target.primitive_type() {
-                Some(prim) => prim,
-                None => continue,
-            }
-        };
-        let did = match primitive {
-            Isize => tcx.lang_items().isize_impl(),
-            I8 => tcx.lang_items().i8_impl(),
-            I16 => tcx.lang_items().i16_impl(),
-            I32 => tcx.lang_items().i32_impl(),
-            I64 => tcx.lang_items().i64_impl(),
-            I128 => tcx.lang_items().i128_impl(),
-            Usize => tcx.lang_items().usize_impl(),
-            U8 => tcx.lang_items().u8_impl(),
-            U16 => tcx.lang_items().u16_impl(),
-            U32 => tcx.lang_items().u32_impl(),
-            U64 => tcx.lang_items().u64_impl(),
-            U128 => tcx.lang_items().u128_impl(),
-            F32 => tcx.lang_items().f32_impl(),
-            F64 => tcx.lang_items().f64_impl(),
-            Char => tcx.lang_items().char_impl(),
-            Bool => tcx.lang_items().bool_impl(),
-            Str => tcx.lang_items().str_impl(),
-            Slice => tcx.lang_items().slice_impl(),
-            Array => tcx.lang_items().slice_impl(),
-            Tuple => None,
-            Unit => None,
-            RawPointer => tcx.lang_items().const_ptr_impl(),
-            Reference => None,
-            Fn => None,
-            Never => None,
-        };
-        if let Some(did) = did {
-            if !did.is_local() {
-                inline::build_impl(cx, did, None, ret);
-            }
-        }
-    }
-}
-
 impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
 
@@ -4115,20 +2271,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub enum Import {
-    // use source as str;
-    Simple(String, ImportSource),
-    // use source::*;
-    Glob(ImportSource)
-}
-
-#[derive(Clone, Debug)]
-pub struct ImportSource {
-    pub path: Path,
-    pub did: Option<DefId>,
-}
-
 impl Clean<Item> for doctree::ForeignItem<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let inner = match self.kind {
@@ -4176,176 +2318,6 @@
     }
 }
 
-// Utilities
-
-pub trait ToSource {
-    fn to_src(&self, cx: &DocContext<'_>) -> String;
-}
-
-impl ToSource for syntax_pos::Span {
-    fn to_src(&self, cx: &DocContext<'_>) -> String {
-        debug!("converting span {:?} to snippet", self.clean(cx));
-        let sn = match cx.sess().source_map().span_to_snippet(*self) {
-            Ok(x) => x,
-            Err(_) => String::new()
-        };
-        debug!("got snippet {}", sn);
-        sn
-    }
-}
-
-fn name_from_pat(p: &hir::Pat) -> String {
-    use rustc::hir::*;
-    debug!("trying to get a name from pattern: {:?}", p);
-
-    match p.kind {
-        PatKind::Wild => "_".to_string(),
-        PatKind::Binding(_, _, ident, _) => ident.to_string(),
-        PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
-        PatKind::Struct(ref name, ref fields, etc) => {
-            format!("{} {{ {}{} }}", qpath_to_string(name),
-                fields.iter().map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat)))
-                             .collect::<Vec<String>>().join(", "),
-                if etc { ", .." } else { "" }
-            )
-        }
-        PatKind::Or(ref pats) => {
-            pats.iter().map(|p| name_from_pat(&**p)).collect::<Vec<String>>().join(" | ")
-        }
-        PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
-                                            .collect::<Vec<String>>().join(", ")),
-        PatKind::Box(ref p) => name_from_pat(&**p),
-        PatKind::Ref(ref p, _) => name_from_pat(&**p),
-        PatKind::Lit(..) => {
-            warn!("tried to get argument name from PatKind::Lit, \
-                  which is silly in function arguments");
-            "()".to_string()
-        },
-        PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
-                              which is not allowed in function arguments"),
-        PatKind::Slice(ref begin, ref mid, ref end) => {
-            let begin = begin.iter().map(|p| name_from_pat(&**p));
-            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
-            let end = end.iter().map(|p| name_from_pat(&**p));
-            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
-        },
-    }
-}
-
-fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
-    match n.val {
-        ty::ConstKind::Unevaluated(def_id, _) => {
-            if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
-                print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
-            } else {
-                inline::print_inlined_const(cx, def_id)
-            }
-        },
-        _ => {
-            let mut s = n.to_string();
-            // array lengths are obviously usize
-            if s.ends_with("usize") {
-                let n = s.len() - "usize".len();
-                s.truncate(n);
-                if s.ends_with(": ") {
-                    let n = s.len() - ": ".len();
-                    s.truncate(n);
-                }
-            }
-            s
-        },
-    }
-}
-
-fn print_const_expr(cx: &DocContext<'_>, body: hir::BodyId) -> String {
-    cx.tcx.hir().hir_to_pretty_string(body.hir_id)
-}
-
-/// Given a type Path, resolve it to a Type using the TyCtxt
-fn resolve_type(cx: &DocContext<'_>,
-                path: Path,
-                id: hir::HirId) -> Type {
-    if id == hir::DUMMY_HIR_ID {
-        debug!("resolve_type({:?})", path);
-    } else {
-        debug!("resolve_type({:?},{:?})", path, id);
-    }
-
-    let is_generic = match path.res {
-        Res::PrimTy(p) => match p {
-            hir::Str => return Primitive(PrimitiveType::Str),
-            hir::Bool => return Primitive(PrimitiveType::Bool),
-            hir::Char => return Primitive(PrimitiveType::Char),
-            hir::Int(int_ty) => return Primitive(int_ty.into()),
-            hir::Uint(uint_ty) => return Primitive(uint_ty.into()),
-            hir::Float(float_ty) => return Primitive(float_ty.into()),
-        },
-        Res::SelfTy(..) if path.segments.len() == 1 => {
-            return Generic(kw::SelfUpper.to_string());
-        }
-        Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
-            return Generic(format!("{:#}", path.print()));
-        }
-        Res::SelfTy(..)
-        | Res::Def(DefKind::TyParam, _)
-        | Res::Def(DefKind::AssocTy, _) => true,
-        _ => false,
-    };
-    let did = register_res(&*cx, path.res);
-    ResolvedPath { path, param_names: None, did, is_generic }
-}
-
-pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId {
-    debug!("register_res({:?})", res);
-
-    let (did, kind) = match res {
-        Res::Def(DefKind::Fn, i) => (i, TypeKind::Function),
-        Res::Def(DefKind::TyAlias, i) => (i, TypeKind::Typedef),
-        Res::Def(DefKind::Enum, i) => (i, TypeKind::Enum),
-        Res::Def(DefKind::Trait, i) => (i, TypeKind::Trait),
-        Res::Def(DefKind::Struct, i) => (i, TypeKind::Struct),
-        Res::Def(DefKind::Union, i) => (i, TypeKind::Union),
-        Res::Def(DefKind::Mod, i) => (i, TypeKind::Module),
-        Res::Def(DefKind::ForeignTy, i) => (i, TypeKind::Foreign),
-        Res::Def(DefKind::Const, i) => (i, TypeKind::Const),
-        Res::Def(DefKind::Static, i) => (i, TypeKind::Static),
-        Res::Def(DefKind::Variant, i) => (cx.tcx.parent(i).expect("cannot get parent def id"),
-                            TypeKind::Enum),
-        Res::Def(DefKind::Macro(mac_kind), i) => match mac_kind {
-            MacroKind::Bang => (i, TypeKind::Macro),
-            MacroKind::Attr => (i, TypeKind::Attr),
-            MacroKind::Derive => (i, TypeKind::Derive),
-        },
-        Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias),
-        Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
-        Res::SelfTy(_, Some(impl_def_id)) => return impl_def_id,
-        _ => return res.def_id()
-    };
-    if did.is_local() { return did }
-    inline::record_extern_fqn(cx, did, kind);
-    if let TypeKind::Trait = kind {
-        inline::record_extern_trait(cx, did);
-    }
-    did
-}
-
-fn resolve_use_source(cx: &DocContext<'_>, path: Path) -> ImportSource {
-    ImportSource {
-        did: if path.res.opt_def_id().is_none() {
-            None
-        } else {
-            Some(register_res(cx, path.res))
-        },
-        path,
-    }
-}
-
-#[derive(Clone, Debug)]
-pub struct Macro {
-    pub source: String,
-    pub imported_from: Option<String>,
-}
-
 impl Clean<Item> for doctree::Macro<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let name = self.name.clean(cx);
@@ -4369,12 +2341,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct ProcMacro {
-    pub kind: MacroKind,
-    pub helpers: Vec<String>,
-}
-
 impl Clean<Item> for doctree::ProcMacro<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         Item {
@@ -4393,22 +2359,6 @@
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Stability {
-    pub level: stability::StabilityLevel,
-    pub feature: Option<String>,
-    pub since: String,
-    pub deprecation: Option<Deprecation>,
-    pub unstable_reason: Option<String>,
-    pub issue: Option<NonZeroU32>,
-}
-
-#[derive(Clone, Debug)]
-pub struct Deprecation {
-    pub since: Option<String>,
-    pub note: Option<String>,
-}
-
 impl Clean<Stability> for attr::Stability {
     fn clean(&self, _: &DocContext<'_>) -> Stability {
         Stability {
@@ -4451,33 +2401,6 @@
     }
 }
 
-/// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
-/// `A: Send + Sync` in `Foo<A: Send + Sync>`).
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct TypeBinding {
-    pub name: String,
-    pub kind: TypeBindingKind,
-}
-
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum TypeBindingKind {
-    Equality {
-        ty: Type,
-    },
-    Constraint {
-        bounds: Vec<GenericBound>,
-    },
-}
-
-impl TypeBinding {
-    pub fn ty(&self) -> &Type {
-        match self.kind {
-            TypeBindingKind::Equality { ref ty } => ty,
-            _ => panic!("expected equality type binding for parenthesized generic args"),
-        }
-    }
-}
-
 impl Clean<TypeBinding> for hir::TypeBinding {
     fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
         TypeBinding {
@@ -4502,29 +2425,6 @@
     }
 }
 
-pub fn enter_impl_trait<F, R>(cx: &DocContext<'_>, f: F) -> R
-where
-    F: FnOnce() -> R,
-{
-    let old_bounds = mem::take(&mut *cx.impl_trait_bounds.borrow_mut());
-    let r = f();
-    assert!(cx.impl_trait_bounds.borrow().is_empty());
-    *cx.impl_trait_bounds.borrow_mut() = old_bounds;
-    r
-}
-
-#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
-enum RegionTarget<'tcx> {
-    Region(Region<'tcx>),
-    RegionVid(RegionVid)
-}
-
-#[derive(Default, Debug, Clone)]
-struct RegionDeps<'tcx> {
-    larger: FxHashSet<RegionTarget<'tcx>>,
-    smaller: FxHashSet<RegionTarget<'tcx>>
-}
-
 enum SimpleBound {
     TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
     Outlives(Lifetime),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
new file mode 100644
index 0000000..bd3f2a3
--- /dev/null
+++ b/src/librustdoc/clean/types.rs
@@ -0,0 +1,1545 @@
+use std::fmt;
+use std::hash::{Hash, Hasher};
+use std::default::Default;
+use std::{slice, vec};
+use std::num::NonZeroU32;
+use std::iter::FromIterator;
+use std::rc::Rc;
+use std::cell::RefCell;
+use std::sync::Arc;
+
+use rustc::middle::lang_items;
+use rustc::middle::stability;
+use rustc::hir;
+use rustc::hir::def::Res;
+use rustc::hir::def_id::{CrateNum, DefId};
+use rustc::ty::layout::VariantIdx;
+use rustc::util::nodemap::{FxHashMap, FxHashSet};
+use rustc_index::vec::IndexVec;
+use rustc_target::spec::abi::Abi;
+use syntax::ast::{self, Attribute, AttrStyle, AttrKind, Ident};
+use syntax::attr;
+use syntax::util::comments;
+use syntax::source_map::DUMMY_SP;
+use syntax_pos::hygiene::MacroKind;
+use syntax_pos::symbol::{Symbol, sym};
+use syntax_pos::{self, FileName};
+
+use crate::core::DocContext;
+use crate::clean::cfg::Cfg;
+use crate::clean::inline;
+use crate::clean::external_path;
+use crate::clean::types::Type::{QPath, ResolvedPath};
+use crate::doctree;
+use crate::html::item_type::ItemType;
+use crate::html::render::{cache, ExternalLocation};
+
+use self::Type::*;
+use self::ItemEnum::*;
+use self::SelfTy::*;
+use self::FunctionRetTy::*;
+
+thread_local!(pub static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
+
+#[derive(Clone, Debug)]
+pub struct Crate {
+    pub name: String,
+    pub version: Option<String>,
+    pub src: FileName,
+    pub module: Option<Item>,
+    pub externs: Vec<(CrateNum, ExternalCrate)>,
+    pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
+    // These are later on moved into `CACHEKEY`, leaving the map empty.
+    // Only here so that they can be filtered through the rustdoc passes.
+    pub external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
+    pub masked_crates: FxHashSet<CrateNum>,
+    pub collapsed: bool,
+}
+
+#[derive(Clone, Debug)]
+pub struct ExternalCrate {
+    pub name: String,
+    pub src: FileName,
+    pub attrs: Attributes,
+    pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
+    pub keywords: Vec<(DefId, String, Attributes)>,
+}
+
+/// Anything with a source location and set of attributes and, optionally, a
+/// name. That is, anything that can be documented. This doesn't correspond
+/// directly to the AST's concept of an item; it's a strict superset.
+#[derive(Clone)]
+pub struct Item {
+    /// Stringified span
+    pub source: Span,
+    /// Not everything has a name. E.g., impls
+    pub name: Option<String>,
+    pub attrs: Attributes,
+    pub inner: ItemEnum,
+    pub visibility: Visibility,
+    pub def_id: DefId,
+    pub stability: Option<Stability>,
+    pub deprecation: Option<Deprecation>,
+}
+
+impl fmt::Debug for Item {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let fake = MAX_DEF_ID.with(|m| m.borrow().get(&self.def_id.krate)
+                                   .map(|id| self.def_id >= *id).unwrap_or(false));
+        let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
+
+        fmt.debug_struct("Item")
+            .field("source", &self.source)
+            .field("name", &self.name)
+            .field("attrs", &self.attrs)
+            .field("inner", &self.inner)
+            .field("visibility", &self.visibility)
+            .field("def_id", def_id)
+            .field("stability", &self.stability)
+            .field("deprecation", &self.deprecation)
+            .finish()
+    }
+}
+
+impl Item {
+    /// Finds the `doc` attribute as a NameValue and returns the corresponding
+    /// value found.
+    pub fn doc_value(&self) -> Option<&str> {
+        self.attrs.doc_value()
+    }
+
+    /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
+    /// with newlines.
+    pub fn collapsed_doc_value(&self) -> Option<String> {
+        self.attrs.collapsed_doc_value()
+    }
+
+    pub fn links(&self) -> Vec<(String, String)> {
+        self.attrs.links(&self.def_id.krate)
+    }
+
+    pub fn is_crate(&self) -> bool {
+        match self.inner {
+            StrippedItem(box ModuleItem(Module { is_crate: true, ..})) |
+            ModuleItem(Module { is_crate: true, ..}) => true,
+            _ => false,
+        }
+    }
+    pub fn is_mod(&self) -> bool {
+        self.type_() == ItemType::Module
+    }
+    pub fn is_trait(&self) -> bool {
+        self.type_() == ItemType::Trait
+    }
+    pub fn is_struct(&self) -> bool {
+        self.type_() == ItemType::Struct
+    }
+    pub fn is_enum(&self) -> bool {
+        self.type_() == ItemType::Enum
+    }
+    pub fn is_variant(&self) -> bool {
+        self.type_() == ItemType::Variant
+    }
+    pub fn is_associated_type(&self) -> bool {
+        self.type_() == ItemType::AssocType
+    }
+    pub fn is_associated_const(&self) -> bool {
+        self.type_() == ItemType::AssocConst
+    }
+    pub fn is_method(&self) -> bool {
+        self.type_() == ItemType::Method
+    }
+    pub fn is_ty_method(&self) -> bool {
+        self.type_() == ItemType::TyMethod
+    }
+    pub fn is_typedef(&self) -> bool {
+        self.type_() == ItemType::Typedef
+    }
+    pub fn is_primitive(&self) -> bool {
+        self.type_() == ItemType::Primitive
+    }
+    pub fn is_union(&self) -> bool {
+        self.type_() == ItemType::Union
+    }
+    pub fn is_import(&self) -> bool {
+        self.type_() == ItemType::Import
+    }
+    pub fn is_extern_crate(&self) -> bool {
+        self.type_() == ItemType::ExternCrate
+    }
+    pub fn is_keyword(&self) -> bool {
+        self.type_() == ItemType::Keyword
+    }
+    pub fn is_stripped(&self) -> bool {
+        match self.inner { StrippedItem(..) => true, _ => false }
+    }
+    pub fn has_stripped_fields(&self) -> Option<bool> {
+        match self.inner {
+            StructItem(ref _struct) => Some(_struct.fields_stripped),
+            UnionItem(ref union) => Some(union.fields_stripped),
+            VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)} ) => {
+                Some(vstruct.fields_stripped)
+            },
+            _ => None,
+        }
+    }
+
+    pub fn stability_class(&self) -> Option<String> {
+        self.stability.as_ref().and_then(|ref s| {
+            let mut classes = Vec::with_capacity(2);
+
+            if s.level == stability::Unstable {
+                classes.push("unstable");
+            }
+
+            if s.deprecation.is_some() {
+                classes.push("deprecated");
+            }
+
+            if classes.len() != 0 {
+                Some(classes.join(" "))
+            } else {
+                None
+            }
+        })
+    }
+
+    pub fn stable_since(&self) -> Option<&str> {
+        self.stability.as_ref().map(|s| &s.since[..])
+    }
+
+    pub fn is_non_exhaustive(&self) -> bool {
+        self.attrs.other_attrs.iter()
+            .any(|a| a.check_name(sym::non_exhaustive))
+    }
+
+    /// Returns a documentation-level item type from the item.
+    pub fn type_(&self) -> ItemType {
+        ItemType::from(self)
+    }
+
+    /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
+    ///
+    /// If the item is not deprecated, returns `None`.
+    pub fn deprecation(&self) -> Option<&Deprecation> {
+        self.deprecation
+            .as_ref()
+            .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref()))
+    }
+    pub fn is_default(&self) -> bool {
+        match self.inner {
+            ItemEnum::MethodItem(ref meth) => {
+                if let Some(defaultness) = meth.defaultness {
+                    defaultness.has_value() && !defaultness.is_final()
+                } else {
+                    false
+                }
+            }
+            _ => false,
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+pub enum ItemEnum {
+    ExternCrateItem(String, Option<String>),
+    ImportItem(Import),
+    StructItem(Struct),
+    UnionItem(Union),
+    EnumItem(Enum),
+    FunctionItem(Function),
+    ModuleItem(Module),
+    TypedefItem(Typedef, bool /* is associated type */),
+    OpaqueTyItem(OpaqueTy, bool /* is associated type */),
+    StaticItem(Static),
+    ConstantItem(Constant),
+    TraitItem(Trait),
+    TraitAliasItem(TraitAlias),
+    ImplItem(Impl),
+    /// A method signature only. Used for required methods in traits (ie,
+    /// non-default-methods).
+    TyMethodItem(TyMethod),
+    /// A method with a body.
+    MethodItem(Method),
+    StructFieldItem(Type),
+    VariantItem(Variant),
+    /// `fn`s from an extern block
+    ForeignFunctionItem(Function),
+    /// `static`s from an extern block
+    ForeignStaticItem(Static),
+    /// `type`s from an extern block
+    ForeignTypeItem,
+    MacroItem(Macro),
+    ProcMacroItem(ProcMacro),
+    PrimitiveItem(PrimitiveType),
+    AssocConstItem(Type, Option<String>),
+    AssocTypeItem(Vec<GenericBound>, Option<Type>),
+    /// An item that has been stripped by a rustdoc pass
+    StrippedItem(Box<ItemEnum>),
+    KeywordItem(String),
+}
+
+impl ItemEnum {
+    pub fn is_associated(&self) -> bool {
+        match *self {
+            ItemEnum::TypedefItem(_, _) |
+            ItemEnum::AssocTypeItem(_, _) => true,
+            _ => false,
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct Module {
+    pub items: Vec<Item>,
+    pub is_crate: bool,
+}
+
+pub struct ListAttributesIter<'a> {
+    attrs: slice::Iter<'a, ast::Attribute>,
+    current_list: vec::IntoIter<ast::NestedMetaItem>,
+    name: Symbol,
+}
+
+impl<'a> Iterator for ListAttributesIter<'a> {
+    type Item = ast::NestedMetaItem;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if let Some(nested) = self.current_list.next() {
+            return Some(nested);
+        }
+
+        for attr in &mut self.attrs {
+            if let Some(list) = attr.meta_item_list() {
+                if attr.check_name(self.name) {
+                    self.current_list = list.into_iter();
+                    if let Some(nested) = self.current_list.next() {
+                        return Some(nested);
+                    }
+                }
+            }
+        }
+
+        None
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let lower = self.current_list.len();
+        (lower, None)
+    }
+}
+
+pub trait AttributesExt {
+    /// Finds an attribute as List and returns the list of attributes nested inside.
+    fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
+}
+
+impl AttributesExt for [ast::Attribute] {
+    fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
+        ListAttributesIter {
+            attrs: self.iter(),
+            current_list: Vec::new().into_iter(),
+            name,
+        }
+    }
+}
+
+pub trait NestedAttributesExt {
+    /// Returns `true` if the attribute list contains a specific `Word`
+    fn has_word(self, word: Symbol) -> bool;
+}
+
+impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I {
+    fn has_word(self, word: Symbol) -> bool {
+        self.into_iter().any(|attr| attr.is_word() && attr.check_name(word))
+    }
+}
+
+/// A portion of documentation, extracted from a `#[doc]` attribute.
+///
+/// Each variant contains the line number within the complete doc-comment where the fragment
+/// starts, as well as the Span where the corresponding doc comment or attribute is located.
+///
+/// Included files are kept separate from inline doc comments so that proper line-number
+/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
+/// kept separate because of issue #42760.
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum DocFragment {
+    /// A doc fragment created from a `///` or `//!` doc comment.
+    SugaredDoc(usize, syntax_pos::Span, String),
+    /// A doc fragment created from a "raw" `#[doc=""]` attribute.
+    RawDoc(usize, syntax_pos::Span, String),
+    /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
+    /// given filename and the file contents.
+    Include(usize, syntax_pos::Span, String, String),
+}
+
+impl DocFragment {
+    pub fn as_str(&self) -> &str {
+        match *self {
+            DocFragment::SugaredDoc(_, _, ref s) => &s[..],
+            DocFragment::RawDoc(_, _, ref s) => &s[..],
+            DocFragment::Include(_, _, _, ref s) => &s[..],
+        }
+    }
+
+    pub fn span(&self) -> syntax_pos::Span {
+        match *self {
+            DocFragment::SugaredDoc(_, span, _) |
+                DocFragment::RawDoc(_, span, _) |
+                DocFragment::Include(_, span, _, _) => span,
+        }
+    }
+}
+
+impl<'a> FromIterator<&'a DocFragment> for String {
+    fn from_iter<T>(iter: T) -> Self
+    where
+        T: IntoIterator<Item = &'a DocFragment>
+    {
+        iter.into_iter().fold(String::new(), |mut acc, frag| {
+            if !acc.is_empty() {
+                acc.push('\n');
+            }
+            match *frag {
+                DocFragment::SugaredDoc(_, _, ref docs)
+                    | DocFragment::RawDoc(_, _, ref docs)
+                    | DocFragment::Include(_, _, _, ref docs) =>
+                    acc.push_str(docs),
+            }
+
+            acc
+        })
+    }
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct Attributes {
+    pub doc_strings: Vec<DocFragment>,
+    pub other_attrs: Vec<ast::Attribute>,
+    pub cfg: Option<Arc<Cfg>>,
+    pub span: Option<syntax_pos::Span>,
+    /// map from Rust paths to resolved defs and potential URL fragments
+    pub links: Vec<(String, Option<DefId>, Option<String>)>,
+    pub inner_docs: bool,
+}
+
+impl Attributes {
+    /// Extracts the content from an attribute `#[doc(cfg(content))]`.
+    pub fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
+        use syntax::ast::NestedMetaItem::MetaItem;
+
+        if let ast::MetaItemKind::List(ref nmis) = mi.kind {
+            if nmis.len() == 1 {
+                if let MetaItem(ref cfg_mi) = nmis[0] {
+                    if cfg_mi.check_name(sym::cfg) {
+                        if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.kind {
+                            if cfg_nmis.len() == 1 {
+                                if let MetaItem(ref content_mi) = cfg_nmis[0] {
+                                    return Some(content_mi);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        None
+    }
+
+    /// Reads a `MetaItem` from within an attribute, looks for whether it is a
+    /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
+    /// its expansion.
+    pub fn extract_include(mi: &ast::MetaItem) -> Option<(String, String)> {
+        mi.meta_item_list().and_then(|list| {
+            for meta in list {
+                if meta.check_name(sym::include) {
+                    // the actual compiled `#[doc(include="filename")]` gets expanded to
+                    // `#[doc(include(file="filename", contents="file contents")]` so we need to
+                    // look for that instead
+                    return meta.meta_item_list().and_then(|list| {
+                        let mut filename: Option<String> = None;
+                        let mut contents: Option<String> = None;
+
+                        for it in list {
+                            if it.check_name(sym::file) {
+                                if let Some(name) = it.value_str() {
+                                    filename = Some(name.to_string());
+                                }
+                            } else if it.check_name(sym::contents) {
+                                if let Some(docs) = it.value_str() {
+                                    contents = Some(docs.to_string());
+                                }
+                            }
+                        }
+
+                        if let (Some(filename), Some(contents)) = (filename, contents) {
+                            Some((filename, contents))
+                        } else {
+                            None
+                        }
+                    });
+                }
+            }
+
+            None
+        })
+    }
+
+    pub fn has_doc_flag(&self, flag: Symbol) -> bool {
+        for attr in &self.other_attrs {
+            if !attr.check_name(sym::doc) { continue; }
+
+            if let Some(items) = attr.meta_item_list() {
+                if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) {
+                    return true;
+                }
+            }
+        }
+
+        false
+    }
+
+    pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
+        let mut doc_strings = vec![];
+        let mut sp = None;
+        let mut cfg = Cfg::True;
+        let mut doc_line = 0;
+
+        /// If `attr` is a doc comment, strips the leading and (if present)
+        /// trailing comments symbols, e.g. `///`, `/**`, and `*/`. Otherwise,
+        /// returns `attr` unchanged.
+        pub fn with_doc_comment_markers_stripped<T>(
+            attr: &Attribute,
+            f: impl FnOnce(&Attribute) -> T,
+        ) -> T {
+            match attr.kind {
+                AttrKind::Normal(_) => {
+                    f(attr)
+                }
+                AttrKind::DocComment(comment) => {
+                    let comment =
+                        Symbol::intern(&comments::strip_doc_comment_decoration(&comment.as_str()));
+                    f(&Attribute {
+                        kind: AttrKind::DocComment(comment),
+                        id: attr.id,
+                        style: attr.style,
+                        span: attr.span,
+                    })
+                }
+            }
+        }
+
+        let other_attrs = attrs.iter().filter_map(|attr| {
+            with_doc_comment_markers_stripped(attr, |attr| {
+                if attr.check_name(sym::doc) {
+                    if let Some(mi) = attr.meta() {
+                        if let Some(value) = mi.value_str() {
+                            // Extracted #[doc = "..."]
+                            let value = value.to_string();
+                            let line = doc_line;
+                            doc_line += value.lines().count();
+
+                            if attr.is_doc_comment() {
+                                doc_strings.push(DocFragment::SugaredDoc(line, attr.span, value));
+                            } else {
+                                doc_strings.push(DocFragment::RawDoc(line, attr.span, value));
+                            }
+
+                            if sp.is_none() {
+                                sp = Some(attr.span);
+                            }
+                            return None;
+                        } else if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
+                            // Extracted #[doc(cfg(...))]
+                            match Cfg::parse(cfg_mi) {
+                                Ok(new_cfg) => cfg &= new_cfg,
+                                Err(e) => diagnostic.span_err(e.span, e.msg),
+                            }
+                            return None;
+                        } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
+                        {
+                            let line = doc_line;
+                            doc_line += contents.lines().count();
+                            doc_strings.push(DocFragment::Include(line,
+                                                                  attr.span,
+                                                                  filename,
+                                                                  contents));
+                        }
+                    }
+                }
+                Some(attr.clone())
+            })
+        }).collect();
+
+        // treat #[target_feature(enable = "feat")] attributes as if they were
+        // #[doc(cfg(target_feature = "feat"))] attributes as well
+        for attr in attrs.lists(sym::target_feature) {
+            if attr.check_name(sym::enable) {
+                if let Some(feat) = attr.value_str() {
+                    let meta = attr::mk_name_value_item_str(
+                        Ident::with_dummy_span(sym::target_feature), feat, DUMMY_SP
+                    );
+                    if let Ok(feat_cfg) = Cfg::parse(&meta) {
+                        cfg &= feat_cfg;
+                    }
+                }
+            }
+        }
+
+        let inner_docs = attrs.iter()
+                              .filter(|a| a.check_name(sym::doc))
+                              .next()
+                              .map_or(true, |a| a.style == AttrStyle::Inner);
+
+        Attributes {
+            doc_strings,
+            other_attrs,
+            cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
+            span: sp,
+            links: vec![],
+            inner_docs,
+        }
+    }
+
+    /// Finds the `doc` attribute as a NameValue and returns the corresponding
+    /// value found.
+    pub fn doc_value(&self) -> Option<&str> {
+        self.doc_strings.first().map(|s| s.as_str())
+    }
+
+    /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
+    /// with newlines.
+    pub fn collapsed_doc_value(&self) -> Option<String> {
+        if !self.doc_strings.is_empty() {
+            Some(self.doc_strings.iter().collect())
+        } else {
+            None
+        }
+    }
+
+    /// Gets links as a vector
+    ///
+    /// Cache must be populated before call
+    pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> {
+        use crate::html::format::href;
+
+        self.links.iter().filter_map(|&(ref s, did, ref fragment)| {
+            match did {
+                Some(did) => {
+                    if let Some((mut href, ..)) = href(did) {
+                        if let Some(ref fragment) = *fragment {
+                            href.push_str("#");
+                            href.push_str(fragment);
+                        }
+                        Some((s.clone(), href))
+                    } else {
+                        None
+                    }
+                }
+                None => {
+                    if let Some(ref fragment) = *fragment {
+                        let cache = cache();
+                        let url = match cache.extern_locations.get(krate) {
+                            Some(&(_, ref src, ExternalLocation::Local)) =>
+                                src.to_str().expect("invalid file path"),
+                            Some(&(_, _, ExternalLocation::Remote(ref s))) => s,
+                            Some(&(_, _, ExternalLocation::Unknown)) | None =>
+                                "https://doc.rust-lang.org/nightly",
+                        };
+                        // This is a primitive so the url is done "by hand".
+                        let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
+                        Some((s.clone(),
+                              format!("{}{}std/primitive.{}.html{}",
+                                      url,
+                                      if !url.ends_with('/') { "/" } else { "" },
+                                      &fragment[..tail],
+                                      &fragment[tail..])))
+                    } else {
+                        panic!("This isn't a primitive?!");
+                    }
+                }
+            }
+        }).collect()
+    }
+}
+
+impl PartialEq for Attributes {
+    fn eq(&self, rhs: &Self) -> bool {
+        self.doc_strings == rhs.doc_strings &&
+        self.cfg == rhs.cfg &&
+        self.span == rhs.span &&
+        self.links == rhs.links &&
+        self.other_attrs.iter().map(|attr| attr.id).eq(rhs.other_attrs.iter().map(|attr| attr.id))
+    }
+}
+
+impl Eq for Attributes {}
+
+impl Hash for Attributes {
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        self.doc_strings.hash(hasher);
+        self.cfg.hash(hasher);
+        self.span.hash(hasher);
+        self.links.hash(hasher);
+        for attr in &self.other_attrs {
+            attr.id.hash(hasher);
+        }
+    }
+}
+
+impl AttributesExt for Attributes {
+    fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
+        self.other_attrs.lists(name)
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum GenericBound {
+    TraitBound(PolyTrait, hir::TraitBoundModifier),
+    Outlives(Lifetime),
+}
+
+impl GenericBound {
+    pub fn maybe_sized(cx: &DocContext<'_>) -> GenericBound {
+        let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
+        let empty = cx.tcx.intern_substs(&[]);
+        let path = external_path(cx, cx.tcx.item_name(did),
+            Some(did), false, vec![], empty);
+        inline::record_extern_fqn(cx, did, TypeKind::Trait);
+        GenericBound::TraitBound(PolyTrait {
+            trait_: ResolvedPath {
+                path,
+                param_names: None,
+                did,
+                is_generic: false,
+            },
+            generic_params: Vec::new(),
+        }, hir::TraitBoundModifier::Maybe)
+    }
+
+    pub fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
+        use rustc::hir::TraitBoundModifier as TBM;
+        if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
+            if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
+                return true;
+            }
+        }
+        false
+    }
+
+    pub fn get_poly_trait(&self) -> Option<PolyTrait> {
+        if let GenericBound::TraitBound(ref p, _) = *self {
+            return Some(p.clone())
+        }
+        None
+    }
+
+    pub fn get_trait_type(&self) -> Option<Type> {
+        if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
+            Some(trait_.clone())
+        } else {
+            None
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct Lifetime(pub String);
+
+impl Lifetime {
+    pub fn get_ref<'a>(&'a self) -> &'a str {
+        let Lifetime(ref s) = *self;
+        let s: &'a str = s;
+        s
+    }
+
+    pub fn statik() -> Lifetime {
+        Lifetime("'static".to_string())
+    }
+}
+
+#[derive(Clone, Debug)]
+pub enum WherePredicate {
+    BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
+    RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
+    EqPredicate { lhs: Type, rhs: Type },
+}
+
+impl WherePredicate {
+    pub fn get_bounds(&self) -> Option<&[GenericBound]> {
+        match *self {
+            WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
+            WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
+            _ => None,
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum GenericParamDefKind {
+    Lifetime,
+    Type {
+        did: DefId,
+        bounds: Vec<GenericBound>,
+        default: Option<Type>,
+        synthetic: Option<hir::SyntheticTyParamKind>,
+    },
+    Const {
+        did: DefId,
+        ty: Type,
+    },
+}
+
+impl GenericParamDefKind {
+    pub fn is_type(&self) -> bool {
+        match *self {
+            GenericParamDefKind::Type { .. } => true,
+            _ => false,
+        }
+    }
+
+    // FIXME(eddyb) this either returns the default of a type parameter, or the
+    // type of a `const` parameter. It seems that the intention is to *visit*
+    // any embedded types, but `get_type` seems to be the wrong name for that.
+    pub fn get_type(&self) -> Option<Type> {
+        match self {
+            GenericParamDefKind::Type { default, .. } => default.clone(),
+            GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
+            GenericParamDefKind::Lifetime => None,
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct GenericParamDef {
+    pub name: String,
+    pub kind: GenericParamDefKind,
+}
+
+impl GenericParamDef {
+    pub fn is_synthetic_type_param(&self) -> bool {
+        match self.kind {
+            GenericParamDefKind::Lifetime |
+            GenericParamDefKind::Const { .. } => false,
+            GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
+        }
+    }
+
+    pub fn is_type(&self) -> bool {
+        self.kind.is_type()
+    }
+
+    pub fn get_type(&self) -> Option<Type> {
+        self.kind.get_type()
+    }
+
+    pub fn get_bounds(&self) -> Option<&[GenericBound]> {
+        match self.kind {
+            GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
+            _ => None,
+        }
+    }
+}
+
+// maybe use a Generic enum and use Vec<Generic>?
+#[derive(Clone, Debug, Default)]
+pub struct Generics {
+    pub params: Vec<GenericParamDef>,
+    pub where_predicates: Vec<WherePredicate>,
+}
+
+#[derive(Clone, Debug)]
+pub struct Method {
+    pub generics: Generics,
+    pub decl: FnDecl,
+    pub header: hir::FnHeader,
+    pub defaultness: Option<hir::Defaultness>,
+    pub all_types: Vec<Type>,
+    pub ret_types: Vec<Type>,
+}
+
+#[derive(Clone, Debug)]
+pub struct TyMethod {
+    pub header: hir::FnHeader,
+    pub decl: FnDecl,
+    pub generics: Generics,
+    pub all_types: Vec<Type>,
+    pub ret_types: Vec<Type>,
+}
+
+#[derive(Clone, Debug)]
+pub struct Function {
+    pub decl: FnDecl,
+    pub generics: Generics,
+    pub header: hir::FnHeader,
+    pub all_types: Vec<Type>,
+    pub ret_types: Vec<Type>,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct FnDecl {
+    pub inputs: Arguments,
+    pub output: FunctionRetTy,
+    pub c_variadic: bool,
+    pub attrs: Attributes,
+}
+
+impl FnDecl {
+    pub fn self_type(&self) -> Option<SelfTy> {
+        self.inputs.values.get(0).and_then(|v| v.to_self())
+    }
+
+    /// Returns the sugared return type for an async function.
+    ///
+    /// For example, if the return type is `impl std::future::Future<Output = i32>`, this function
+    /// will return `i32`.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the return type does not match the expected sugaring for async
+    /// functions.
+    pub fn sugared_async_return_type(&self) -> FunctionRetTy {
+        match &self.output {
+            FunctionRetTy::Return(Type::ImplTrait(bounds)) => {
+                match &bounds[0] {
+                    GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => {
+                        let bindings = trait_.bindings().unwrap();
+                        FunctionRetTy::Return(bindings[0].ty().clone())
+                    }
+                    _ => panic!("unexpected desugaring of async function"),
+                }
+            }
+            _ => panic!("unexpected desugaring of async function"),
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct Arguments {
+    pub values: Vec<Argument>,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct Argument {
+    pub type_: Type,
+    pub name: String,
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum SelfTy {
+    SelfValue,
+    SelfBorrowed(Option<Lifetime>, Mutability),
+    SelfExplicit(Type),
+}
+
+impl Argument {
+    pub fn to_self(&self) -> Option<SelfTy> {
+        if self.name != "self" {
+            return None;
+        }
+        if self.type_.is_self_type() {
+            return Some(SelfValue);
+        }
+        match self.type_ {
+            BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => {
+                Some(SelfBorrowed(lifetime.clone(), mutability))
+            }
+            _ => Some(SelfExplicit(self.type_.clone()))
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum FunctionRetTy {
+    Return(Type),
+    DefaultReturn,
+}
+
+impl GetDefId for FunctionRetTy {
+    fn def_id(&self) -> Option<DefId> {
+        match *self {
+            Return(ref ty) => ty.def_id(),
+            DefaultReturn => None,
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct Trait {
+    pub auto: bool,
+    pub unsafety: hir::Unsafety,
+    pub items: Vec<Item>,
+    pub generics: Generics,
+    pub bounds: Vec<GenericBound>,
+    pub is_spotlight: bool,
+    pub is_auto: bool,
+}
+
+#[derive(Clone, Debug)]
+pub struct TraitAlias {
+    pub generics: Generics,
+    pub bounds: Vec<GenericBound>,
+}
+
+/// A trait reference, which may have higher ranked lifetimes.
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct PolyTrait {
+    pub trait_: Type,
+    pub generic_params: Vec<GenericParamDef>,
+}
+
+/// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
+/// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
+/// importantly, it does not preserve mutability or boxes.
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum Type {
+    /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
+    ResolvedPath {
+        path: Path,
+        param_names: Option<Vec<GenericBound>>,
+        did: DefId,
+        /// `true` if is a `T::Name` path for associated types.
+        is_generic: bool,
+    },
+    /// For parameterized types, so the consumer of the JSON don't go
+    /// looking for types which don't exist anywhere.
+    Generic(String),
+    /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
+    /// arrays, slices, and tuples.
+    Primitive(PrimitiveType),
+    /// `extern "ABI" fn`
+    BareFunction(Box<BareFunctionDecl>),
+    Tuple(Vec<Type>),
+    Slice(Box<Type>),
+    Array(Box<Type>, String),
+    Never,
+    RawPointer(Mutability, Box<Type>),
+    BorrowedRef {
+        lifetime: Option<Lifetime>,
+        mutability: Mutability,
+        type_: Box<Type>,
+    },
+
+    // `<Type as Trait>::Name`
+    QPath {
+        name: String,
+        self_type: Box<Type>,
+        trait_: Box<Type>
+    },
+
+    // `_`
+    Infer,
+
+    // `impl TraitA + TraitB + ...`
+    ImplTrait(Vec<GenericBound>),
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
+pub enum PrimitiveType {
+    Isize, I8, I16, I32, I64, I128,
+    Usize, U8, U16, U32, U64, U128,
+    F32, F64,
+    Char,
+    Bool,
+    Str,
+    Slice,
+    Array,
+    Tuple,
+    Unit,
+    RawPointer,
+    Reference,
+    Fn,
+    Never,
+}
+
+#[derive(Clone, Copy, Debug)]
+pub enum TypeKind {
+    Enum,
+    Function,
+    Module,
+    Const,
+    Static,
+    Struct,
+    Union,
+    Trait,
+    Typedef,
+    Foreign,
+    Macro,
+    Attr,
+    Derive,
+    TraitAlias,
+}
+
+pub trait GetDefId {
+    fn def_id(&self) -> Option<DefId>;
+}
+
+impl<T: GetDefId> GetDefId for Option<T> {
+    fn def_id(&self) -> Option<DefId> {
+        self.as_ref().and_then(|d| d.def_id())
+    }
+}
+
+impl Type {
+    pub fn primitive_type(&self) -> Option<PrimitiveType> {
+        match *self {
+            Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
+            Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
+            Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
+            Tuple(ref tys) => if tys.is_empty() {
+                Some(PrimitiveType::Unit)
+            } else {
+                Some(PrimitiveType::Tuple)
+            },
+            RawPointer(..) => Some(PrimitiveType::RawPointer),
+            BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
+            BareFunction(..) => Some(PrimitiveType::Fn),
+            Never => Some(PrimitiveType::Never),
+            _ => None,
+        }
+    }
+
+    pub fn is_generic(&self) -> bool {
+        match *self {
+            ResolvedPath { is_generic, .. } => is_generic,
+            _ => false,
+        }
+    }
+
+    pub fn is_self_type(&self) -> bool {
+        match *self {
+            Generic(ref name) => name == "Self",
+            _ => false
+        }
+    }
+
+    pub fn generics(&self) -> Option<Vec<Type>> {
+        match *self {
+            ResolvedPath { ref path, .. } => {
+                path.segments.last().and_then(|seg| {
+                    if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
+                        Some(args.iter().filter_map(|arg| match arg {
+                            GenericArg::Type(ty) => Some(ty.clone()),
+                            _ => None,
+                        }).collect())
+                    } else {
+                        None
+                    }
+                })
+            }
+            _ => None,
+        }
+    }
+
+    pub fn bindings(&self) -> Option<&[TypeBinding]> {
+        match *self {
+            ResolvedPath { ref path, .. } => {
+                path.segments.last().and_then(|seg| {
+                    if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
+                        Some(&**bindings)
+                    } else {
+                        None
+                    }
+                })
+            }
+            _ => None
+        }
+    }
+
+    pub fn is_full_generic(&self) -> bool {
+        match *self {
+            Type::Generic(_) => true,
+            _ => false,
+        }
+    }
+
+    pub fn projection(&self) -> Option<(&Type, DefId, &str)> {
+        let (self_, trait_, name) = match self {
+            QPath { ref self_type, ref trait_, ref name } => {
+                (self_type, trait_, name)
+            }
+            _ => return None,
+        };
+        let trait_did = match **trait_ {
+            ResolvedPath { did, .. } => did,
+            _ => return None,
+        };
+        Some((&self_, trait_did, name))
+    }
+
+}
+
+impl GetDefId for Type {
+    fn def_id(&self) -> Option<DefId> {
+        match *self {
+            ResolvedPath { did, .. } => Some(did),
+            Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
+            BorrowedRef { type_: box Generic(..), .. } =>
+                Primitive(PrimitiveType::Reference).def_id(),
+            BorrowedRef { ref type_, .. } => type_.def_id(),
+            Tuple(ref tys) => if tys.is_empty() {
+                Primitive(PrimitiveType::Unit).def_id()
+            } else {
+                Primitive(PrimitiveType::Tuple).def_id()
+            },
+            BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
+            Never => Primitive(PrimitiveType::Never).def_id(),
+            Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
+            Array(..) => Primitive(PrimitiveType::Array).def_id(),
+            RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
+            QPath { ref self_type, .. } => self_type.def_id(),
+            _ => None,
+        }
+    }
+}
+
+impl PrimitiveType {
+    pub fn from_str(s: &str) -> Option<PrimitiveType> {
+        match s {
+            "isize" => Some(PrimitiveType::Isize),
+            "i8" => Some(PrimitiveType::I8),
+            "i16" => Some(PrimitiveType::I16),
+            "i32" => Some(PrimitiveType::I32),
+            "i64" => Some(PrimitiveType::I64),
+            "i128" => Some(PrimitiveType::I128),
+            "usize" => Some(PrimitiveType::Usize),
+            "u8" => Some(PrimitiveType::U8),
+            "u16" => Some(PrimitiveType::U16),
+            "u32" => Some(PrimitiveType::U32),
+            "u64" => Some(PrimitiveType::U64),
+            "u128" => Some(PrimitiveType::U128),
+            "bool" => Some(PrimitiveType::Bool),
+            "char" => Some(PrimitiveType::Char),
+            "str" => Some(PrimitiveType::Str),
+            "f32" => Some(PrimitiveType::F32),
+            "f64" => Some(PrimitiveType::F64),
+            "array" => Some(PrimitiveType::Array),
+            "slice" => Some(PrimitiveType::Slice),
+            "tuple" => Some(PrimitiveType::Tuple),
+            "unit" => Some(PrimitiveType::Unit),
+            "pointer" => Some(PrimitiveType::RawPointer),
+            "reference" => Some(PrimitiveType::Reference),
+            "fn" => Some(PrimitiveType::Fn),
+            "never" => Some(PrimitiveType::Never),
+            _ => None,
+        }
+    }
+
+    pub fn as_str(&self) -> &'static str {
+        use self::PrimitiveType::*;
+        match *self {
+            Isize => "isize",
+            I8 => "i8",
+            I16 => "i16",
+            I32 => "i32",
+            I64 => "i64",
+            I128 => "i128",
+            Usize => "usize",
+            U8 => "u8",
+            U16 => "u16",
+            U32 => "u32",
+            U64 => "u64",
+            U128 => "u128",
+            F32 => "f32",
+            F64 => "f64",
+            Str => "str",
+            Bool => "bool",
+            Char => "char",
+            Array => "array",
+            Slice => "slice",
+            Tuple => "tuple",
+            Unit => "unit",
+            RawPointer => "pointer",
+            Reference => "reference",
+            Fn => "fn",
+            Never => "never",
+        }
+    }
+
+    pub fn to_url_str(&self) -> &'static str {
+        self.as_str()
+    }
+}
+
+impl From<ast::IntTy> for PrimitiveType {
+    fn from(int_ty: ast::IntTy) -> PrimitiveType {
+        match int_ty {
+            ast::IntTy::Isize => PrimitiveType::Isize,
+            ast::IntTy::I8 => PrimitiveType::I8,
+            ast::IntTy::I16 => PrimitiveType::I16,
+            ast::IntTy::I32 => PrimitiveType::I32,
+            ast::IntTy::I64 => PrimitiveType::I64,
+            ast::IntTy::I128 => PrimitiveType::I128,
+        }
+    }
+}
+
+impl From<ast::UintTy> for PrimitiveType {
+    fn from(uint_ty: ast::UintTy) -> PrimitiveType {
+        match uint_ty {
+            ast::UintTy::Usize => PrimitiveType::Usize,
+            ast::UintTy::U8 => PrimitiveType::U8,
+            ast::UintTy::U16 => PrimitiveType::U16,
+            ast::UintTy::U32 => PrimitiveType::U32,
+            ast::UintTy::U64 => PrimitiveType::U64,
+            ast::UintTy::U128 => PrimitiveType::U128,
+        }
+    }
+}
+
+impl From<ast::FloatTy> for PrimitiveType {
+    fn from(float_ty: ast::FloatTy) -> PrimitiveType {
+        match float_ty {
+            ast::FloatTy::F32 => PrimitiveType::F32,
+            ast::FloatTy::F64 => PrimitiveType::F64,
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum Visibility {
+    Public,
+    Inherited,
+    Crate,
+    Restricted(DefId, Path),
+}
+
+#[derive(Clone, Debug)]
+pub struct Struct {
+    pub struct_type: doctree::StructType,
+    pub generics: Generics,
+    pub fields: Vec<Item>,
+    pub fields_stripped: bool,
+}
+
+#[derive(Clone, Debug)]
+pub struct Union {
+    pub struct_type: doctree::StructType,
+    pub generics: Generics,
+    pub fields: Vec<Item>,
+    pub fields_stripped: bool,
+}
+
+/// This is a more limited form of the standard Struct, different in that
+/// it lacks the things most items have (name, id, parameterization). Found
+/// only as a variant in an enum.
+#[derive(Clone, Debug)]
+pub struct VariantStruct {
+    pub struct_type: doctree::StructType,
+    pub fields: Vec<Item>,
+    pub fields_stripped: bool,
+}
+
+#[derive(Clone, Debug)]
+pub struct Enum {
+    pub variants: IndexVec<VariantIdx, Item>,
+    pub generics: Generics,
+    pub variants_stripped: bool,
+}
+
+#[derive(Clone, Debug)]
+pub struct Variant {
+    pub kind: VariantKind,
+}
+
+#[derive(Clone, Debug)]
+pub enum VariantKind {
+    CLike,
+    Tuple(Vec<Type>),
+    Struct(VariantStruct),
+}
+
+#[derive(Clone, Debug)]
+pub struct Span {
+    pub filename: FileName,
+    pub loline: usize,
+    pub locol: usize,
+    pub hiline: usize,
+    pub hicol: usize,
+    pub original: syntax_pos::Span,
+}
+
+impl Span {
+    pub fn empty() -> Span {
+        Span {
+            filename: FileName::Anon(0),
+            loline: 0, locol: 0,
+            hiline: 0, hicol: 0,
+            original: syntax_pos::DUMMY_SP,
+        }
+    }
+
+    pub fn span(&self) -> syntax_pos::Span {
+        self.original
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct Path {
+    pub global: bool,
+    pub res: Res,
+    pub segments: Vec<PathSegment>,
+}
+
+impl Path {
+    pub fn last_name(&self) -> &str {
+        self.segments.last().expect("segments were empty").name.as_str()
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum GenericArg {
+    Lifetime(Lifetime),
+    Type(Type),
+    Const(Constant),
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum GenericArgs {
+    AngleBracketed {
+        args: Vec<GenericArg>,
+        bindings: Vec<TypeBinding>,
+    },
+    Parenthesized {
+        inputs: Vec<Type>,
+        output: Option<Type>,
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct PathSegment {
+    pub name: String,
+    pub args: GenericArgs,
+}
+
+#[derive(Clone, Debug)]
+pub struct Typedef {
+    pub type_: Type,
+    pub generics: Generics,
+}
+
+#[derive(Clone, Debug)]
+pub struct OpaqueTy {
+    pub bounds: Vec<GenericBound>,
+    pub generics: Generics,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct BareFunctionDecl {
+    pub unsafety: hir::Unsafety,
+    pub generic_params: Vec<GenericParamDef>,
+    pub decl: FnDecl,
+    pub abi: Abi,
+}
+
+#[derive(Clone, Debug)]
+pub struct Static {
+    pub type_: Type,
+    pub mutability: Mutability,
+    /// It's useful to have the value of a static documented, but I have no
+    /// desire to represent expressions (that'd basically be all of the AST,
+    /// which is huge!). So, have a string.
+    pub expr: String,
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct Constant {
+    pub type_: Type,
+    pub expr: String,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
+pub enum Mutability {
+    Mutable,
+    Immutable,
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum ImplPolarity {
+    Positive,
+    Negative,
+}
+
+#[derive(Clone, Debug)]
+pub struct Impl {
+    pub unsafety: hir::Unsafety,
+    pub generics: Generics,
+    pub provided_trait_methods: FxHashSet<String>,
+    pub trait_: Option<Type>,
+    pub for_: Type,
+    pub items: Vec<Item>,
+    pub polarity: Option<ImplPolarity>,
+    pub synthetic: bool,
+    pub blanket_impl: Option<Type>,
+}
+
+#[derive(Clone, Debug)]
+pub enum Import {
+    // use source as str;
+    Simple(String, ImportSource),
+    // use source::*;
+    Glob(ImportSource)
+}
+
+#[derive(Clone, Debug)]
+pub struct ImportSource {
+    pub path: Path,
+    pub did: Option<DefId>,
+}
+
+#[derive(Clone, Debug)]
+pub struct Macro {
+    pub source: String,
+    pub imported_from: Option<String>,
+}
+
+#[derive(Clone, Debug)]
+pub struct ProcMacro {
+    pub kind: MacroKind,
+    pub helpers: Vec<String>,
+}
+
+#[derive(Clone, Debug)]
+pub struct Stability {
+    pub level: stability::StabilityLevel,
+    pub feature: Option<String>,
+    pub since: String,
+    pub deprecation: Option<Deprecation>,
+    pub unstable_reason: Option<String>,
+    pub issue: Option<NonZeroU32>,
+}
+
+#[derive(Clone, Debug)]
+pub struct Deprecation {
+    pub since: Option<String>,
+    pub note: Option<String>,
+}
+
+/// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
+/// `A: Send + Sync` in `Foo<A: Send + Sync>`).
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct TypeBinding {
+    pub name: String,
+    pub kind: TypeBindingKind,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum TypeBindingKind {
+    Equality {
+        ty: Type,
+    },
+    Constraint {
+        bounds: Vec<GenericBound>,
+    },
+}
+
+impl TypeBinding {
+    pub fn ty(&self) -> &Type {
+        match self.kind {
+            TypeBindingKind::Equality { ref ty } => ty,
+            _ => panic!("expected equality type binding for parenthesized generic args"),
+        }
+    }
+}
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
new file mode 100644
index 0000000..e46300a
--- /dev/null
+++ b/src/librustdoc/clean/utils.rs
@@ -0,0 +1,585 @@
+use crate::core::DocContext;
+use crate::clean::{
+    Clean, Crate, Deprecation, ExternalCrate, FnDecl, FunctionRetTy, Generic, GenericArg,
+    GenericArgs, Generics, GenericBound, GetDefId, ImportSource, Item, ItemEnum, MacroKind, Path,
+    PathSegment, Primitive, PrimitiveType, ResolvedPath, Span, Stability, Type, TypeBinding,
+    TypeKind, Visibility, WherePredicate, inline,
+};
+use crate::clean::blanket_impl::BlanketImplFinder;
+use crate::clean::auto_trait::AutoTraitFinder;
+
+use rustc::hir;
+use rustc::hir::def::{DefKind, Res};
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::ty::{self, DefIdTree, Ty};
+use rustc::ty::subst::{SubstsRef, GenericArgKind};
+use rustc::util::nodemap::FxHashSet;
+use syntax_pos;
+use syntax_pos::symbol::{Symbol, kw, sym};
+
+use std::mem;
+
+pub fn krate(mut cx: &mut DocContext<'_>) -> Crate {
+    use crate::visit_lib::LibEmbargoVisitor;
+
+    let krate = cx.tcx.hir().krate();
+    let module = crate::visit_ast::RustdocVisitor::new(&mut cx).visit(krate);
+
+    let mut r = cx.renderinfo.get_mut();
+    r.deref_trait_did = cx.tcx.lang_items().deref_trait();
+    r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
+    r.owned_box_did = cx.tcx.lang_items().owned_box();
+
+    let mut externs = Vec::new();
+    for &cnum in cx.tcx.crates().iter() {
+        externs.push((cnum, cnum.clean(cx)));
+        // Analyze doc-reachability for extern items
+        LibEmbargoVisitor::new(&mut cx).visit_lib(cnum);
+    }
+    externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
+
+    // Clean the crate, translating the entire libsyntax AST to one that is
+    // understood by rustdoc.
+    let mut module = module.clean(cx);
+    let mut masked_crates = FxHashSet::default();
+
+    match module.inner {
+        ItemEnum::ModuleItem(ref module) => {
+            for it in &module.items {
+                // `compiler_builtins` should be masked too, but we can't apply
+                // `#[doc(masked)]` to the injected `extern crate` because it's unstable.
+                if it.is_extern_crate()
+                    && (it.attrs.has_doc_flag(sym::masked)
+                        || cx.tcx.is_compiler_builtins(it.def_id.krate))
+                {
+                    masked_crates.insert(it.def_id.krate);
+                }
+            }
+        }
+        _ => unreachable!(),
+    }
+
+    let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
+    {
+        let m = match module.inner {
+            ItemEnum::ModuleItem(ref mut m) => m,
+            _ => unreachable!(),
+        };
+        m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| {
+            Item {
+                source: Span::empty(),
+                name: Some(prim.to_url_str().to_string()),
+                attrs: attrs.clone(),
+                visibility: Visibility::Public,
+                stability: get_stability(cx, def_id),
+                deprecation: get_deprecation(cx, def_id),
+                def_id,
+                inner: ItemEnum::PrimitiveItem(prim),
+            }
+        }));
+        m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| {
+            Item {
+                source: Span::empty(),
+                name: Some(kw.clone()),
+                attrs,
+                visibility: Visibility::Public,
+                stability: get_stability(cx, def_id),
+                deprecation: get_deprecation(cx, def_id),
+                def_id,
+                inner: ItemEnum::KeywordItem(kw),
+            }
+        }));
+    }
+
+    Crate {
+        name,
+        version: None,
+        src,
+        module: Some(module),
+        externs,
+        primitives,
+        external_traits: cx.external_traits.clone(),
+        masked_crates,
+        collapsed: false,
+    }
+}
+
+// extract the stability index for a node from tcx, if possible
+pub fn get_stability(cx: &DocContext<'_>, def_id: DefId) -> Option<Stability> {
+    cx.tcx.lookup_stability(def_id).clean(cx)
+}
+
+pub fn get_deprecation(cx: &DocContext<'_>, def_id: DefId) -> Option<Deprecation> {
+    cx.tcx.lookup_deprecation(def_id).clean(cx)
+}
+
+pub fn external_generic_args(
+    cx: &DocContext<'_>,
+    trait_did: Option<DefId>,
+    has_self: bool,
+    bindings: Vec<TypeBinding>,
+    substs: SubstsRef<'_>,
+) -> GenericArgs {
+    let mut skip_self = has_self;
+    let mut ty_kind = None;
+    let args: Vec<_> = substs.iter().filter_map(|kind| match kind.unpack() {
+        GenericArgKind::Lifetime(lt) => {
+            lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt)))
+        }
+        GenericArgKind::Type(_) if skip_self => {
+            skip_self = false;
+            None
+        }
+        GenericArgKind::Type(ty) => {
+            ty_kind = Some(&ty.kind);
+            Some(GenericArg::Type(ty.clean(cx)))
+        }
+        GenericArgKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
+    }).collect();
+
+    match trait_did {
+        // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
+        Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
+            assert!(ty_kind.is_some());
+            let inputs = match ty_kind {
+                Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
+                _ => return GenericArgs::AngleBracketed { args, bindings },
+            };
+            let output = None;
+            // FIXME(#20299) return type comes from a projection now
+            // match types[1].kind {
+            //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
+            //     _ => Some(types[1].clean(cx))
+            // };
+            GenericArgs::Parenthesized { inputs, output }
+        },
+        _ => {
+            GenericArgs::AngleBracketed { args, bindings }
+        }
+    }
+}
+
+// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
+// from Fn<(A, B,), C> to Fn(A, B) -> C
+pub fn external_path(cx: &DocContext<'_>, name: Symbol, trait_did: Option<DefId>, has_self: bool,
+                     bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> Path {
+    Path {
+        global: false,
+        res: Res::Err,
+        segments: vec![PathSegment {
+            name: name.to_string(),
+            args: external_generic_args(cx, trait_did, has_self, bindings, substs)
+        }],
+    }
+}
+
+/// The point of this function is to replace bounds with types.
+///
+/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
+/// `[Display, Option]` (we just returns the list of the types, we don't care about the
+/// wrapped types in here).
+pub fn get_real_types(
+    generics: &Generics,
+    arg: &Type,
+    cx: &DocContext<'_>,
+    recurse: i32,
+) -> FxHashSet<Type> {
+    let arg_s = arg.print().to_string();
+    let mut res = FxHashSet::default();
+    if recurse >= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed
+        return res;
+    }
+    if arg.is_full_generic() {
+        if let Some(where_pred) = generics.where_predicates.iter().find(|g| {
+            match g {
+                &WherePredicate::BoundPredicate { ref ty, .. } => ty.def_id() == arg.def_id(),
+                _ => false,
+            }
+        }) {
+            let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
+            for bound in bounds.iter() {
+                match *bound {
+                    GenericBound::TraitBound(ref poly_trait, _) => {
+                        for x in poly_trait.generic_params.iter() {
+                            if !x.is_type() {
+                                continue
+                            }
+                            if let Some(ty) = x.get_type() {
+                                let adds = get_real_types(generics, &ty, cx, recurse + 1);
+                                if !adds.is_empty() {
+                                    res.extend(adds);
+                                } else if !ty.is_full_generic() {
+                                    res.insert(ty);
+                                }
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+            }
+        }
+        if let Some(bound) = generics.params.iter().find(|g| {
+            g.is_type() && g.name == arg_s
+        }) {
+            for bound in bound.get_bounds().unwrap_or_else(|| &[]) {
+                if let Some(ty) = bound.get_trait_type() {
+                    let adds = get_real_types(generics, &ty, cx, recurse + 1);
+                    if !adds.is_empty() {
+                        res.extend(adds);
+                    } else if !ty.is_full_generic() {
+                        res.insert(ty.clone());
+                    }
+                }
+            }
+        }
+    } else {
+        res.insert(arg.clone());
+        if let Some(gens) = arg.generics() {
+            for gen in gens.iter() {
+                if gen.is_full_generic() {
+                    let adds = get_real_types(generics, gen, cx, recurse + 1);
+                    if !adds.is_empty() {
+                        res.extend(adds);
+                    }
+                } else {
+                    res.insert(gen.clone());
+                }
+            }
+        }
+    }
+    res
+}
+
+/// Return the full list of types when bounds have been resolved.
+///
+/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
+/// `[u32, Display, Option]`.
+pub fn get_all_types(
+    generics: &Generics,
+    decl: &FnDecl,
+    cx: &DocContext<'_>,
+) -> (Vec<Type>, Vec<Type>) {
+    let mut all_types = FxHashSet::default();
+    for arg in decl.inputs.values.iter() {
+        if arg.type_.is_self_type() {
+            continue;
+        }
+        let args = get_real_types(generics, &arg.type_, cx, 0);
+        if !args.is_empty() {
+            all_types.extend(args);
+        } else {
+            all_types.insert(arg.type_.clone());
+        }
+    }
+
+    let ret_types = match decl.output {
+        FunctionRetTy::Return(ref return_type) => {
+            let mut ret = get_real_types(generics, &return_type, cx, 0);
+            if ret.is_empty() {
+                ret.insert(return_type.clone());
+            }
+            ret.into_iter().collect()
+        }
+        _ => Vec::new(),
+    };
+    (all_types.into_iter().collect(), ret_types)
+}
+
+pub fn strip_type(ty: Type) -> Type {
+    match ty {
+        Type::ResolvedPath { path, param_names, did, is_generic } => {
+            Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
+        }
+        Type::Tuple(inner_tys) => {
+            Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
+        }
+        Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))),
+        Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s),
+        Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))),
+        Type::BorrowedRef { lifetime, mutability, type_ } => {
+            Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
+        }
+        Type::QPath { name, self_type, trait_ } => {
+            Type::QPath {
+                name,
+                self_type: Box::new(strip_type(*self_type)), trait_: Box::new(strip_type(*trait_))
+            }
+        }
+        _ => ty
+    }
+}
+
+pub fn strip_path(path: &Path) -> Path {
+    let segments = path.segments.iter().map(|s| {
+        PathSegment {
+            name: s.name.clone(),
+            args: GenericArgs::AngleBracketed {
+                args: vec![],
+                bindings: vec![],
+            }
+        }
+    }).collect();
+
+    Path {
+        global: path.global,
+        res: path.res.clone(),
+        segments,
+    }
+}
+
+pub fn qpath_to_string(p: &hir::QPath) -> String {
+    let segments = match *p {
+        hir::QPath::Resolved(_, ref path) => &path.segments,
+        hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(),
+    };
+
+    let mut s = String::new();
+    for (i, seg) in segments.iter().enumerate() {
+        if i > 0 {
+            s.push_str("::");
+        }
+        if seg.ident.name != kw::PathRoot {
+            s.push_str(&seg.ident.as_str());
+        }
+    }
+    s
+}
+
+pub fn build_deref_target_impls(cx: &DocContext<'_>,
+                                items: &[Item],
+                                ret: &mut Vec<Item>) {
+    use self::PrimitiveType::*;
+    let tcx = cx.tcx;
+
+    for item in items {
+        let target = match item.inner {
+            ItemEnum::TypedefItem(ref t, true) => &t.type_,
+            _ => continue,
+        };
+        let primitive = match *target {
+            ResolvedPath { did, .. } if did.is_local() => continue,
+            ResolvedPath { did, .. } => {
+                ret.extend(inline::build_impls(cx, did, None));
+                continue
+            }
+            _ => match target.primitive_type() {
+                Some(prim) => prim,
+                None => continue,
+            }
+        };
+        let did = match primitive {
+            Isize => tcx.lang_items().isize_impl(),
+            I8 => tcx.lang_items().i8_impl(),
+            I16 => tcx.lang_items().i16_impl(),
+            I32 => tcx.lang_items().i32_impl(),
+            I64 => tcx.lang_items().i64_impl(),
+            I128 => tcx.lang_items().i128_impl(),
+            Usize => tcx.lang_items().usize_impl(),
+            U8 => tcx.lang_items().u8_impl(),
+            U16 => tcx.lang_items().u16_impl(),
+            U32 => tcx.lang_items().u32_impl(),
+            U64 => tcx.lang_items().u64_impl(),
+            U128 => tcx.lang_items().u128_impl(),
+            F32 => tcx.lang_items().f32_impl(),
+            F64 => tcx.lang_items().f64_impl(),
+            Char => tcx.lang_items().char_impl(),
+            Bool => tcx.lang_items().bool_impl(),
+            Str => tcx.lang_items().str_impl(),
+            Slice => tcx.lang_items().slice_impl(),
+            Array => tcx.lang_items().slice_impl(),
+            Tuple => None,
+            Unit => None,
+            RawPointer => tcx.lang_items().const_ptr_impl(),
+            Reference => None,
+            Fn => None,
+            Never => None,
+        };
+        if let Some(did) = did {
+            if !did.is_local() {
+                inline::build_impl(cx, did, None, ret);
+            }
+        }
+    }
+}
+
+pub trait ToSource {
+    fn to_src(&self, cx: &DocContext<'_>) -> String;
+}
+
+impl ToSource for syntax_pos::Span {
+    fn to_src(&self, cx: &DocContext<'_>) -> String {
+        debug!("converting span {:?} to snippet", self.clean(cx));
+        let sn = match cx.sess().source_map().span_to_snippet(*self) {
+            Ok(x) => x,
+            Err(_) => String::new()
+        };
+        debug!("got snippet {}", sn);
+        sn
+    }
+}
+
+pub fn name_from_pat(p: &hir::Pat) -> String {
+    use rustc::hir::*;
+    debug!("trying to get a name from pattern: {:?}", p);
+
+    match p.kind {
+        PatKind::Wild => "_".to_string(),
+        PatKind::Binding(_, _, ident, _) => ident.to_string(),
+        PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
+        PatKind::Struct(ref name, ref fields, etc) => {
+            format!("{} {{ {}{} }}", qpath_to_string(name),
+                fields.iter().map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat)))
+                             .collect::<Vec<String>>().join(", "),
+                if etc { ", .." } else { "" }
+            )
+        }
+        PatKind::Or(ref pats) => {
+            pats.iter().map(|p| name_from_pat(&**p)).collect::<Vec<String>>().join(" | ")
+        }
+        PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
+                                            .collect::<Vec<String>>().join(", ")),
+        PatKind::Box(ref p) => name_from_pat(&**p),
+        PatKind::Ref(ref p, _) => name_from_pat(&**p),
+        PatKind::Lit(..) => {
+            warn!("tried to get argument name from PatKind::Lit, \
+                  which is silly in function arguments");
+            "()".to_string()
+        },
+        PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
+                              which is not allowed in function arguments"),
+        PatKind::Slice(ref begin, ref mid, ref end) => {
+            let begin = begin.iter().map(|p| name_from_pat(&**p));
+            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
+            let end = end.iter().map(|p| name_from_pat(&**p));
+            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
+        },
+    }
+}
+
+pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
+    match n.val {
+        ty::ConstKind::Unevaluated(def_id, _) => {
+            if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
+                print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
+            } else {
+                inline::print_inlined_const(cx, def_id)
+            }
+        },
+        _ => {
+            let mut s = n.to_string();
+            // array lengths are obviously usize
+            if s.ends_with("usize") {
+                let n = s.len() - "usize".len();
+                s.truncate(n);
+                if s.ends_with(": ") {
+                    let n = s.len() - ": ".len();
+                    s.truncate(n);
+                }
+            }
+            s
+        },
+    }
+}
+
+pub fn print_const_expr(cx: &DocContext<'_>, body: hir::BodyId) -> String {
+    cx.tcx.hir().hir_to_pretty_string(body.hir_id)
+}
+
+/// Given a type Path, resolve it to a Type using the TyCtxt
+pub fn resolve_type(cx: &DocContext<'_>,
+                    path: Path,
+                    id: hir::HirId) -> Type {
+    if id == hir::DUMMY_HIR_ID {
+        debug!("resolve_type({:?})", path);
+    } else {
+        debug!("resolve_type({:?},{:?})", path, id);
+    }
+
+    let is_generic = match path.res {
+        Res::PrimTy(p) => match p {
+            hir::Str => return Primitive(PrimitiveType::Str),
+            hir::Bool => return Primitive(PrimitiveType::Bool),
+            hir::Char => return Primitive(PrimitiveType::Char),
+            hir::Int(int_ty) => return Primitive(int_ty.into()),
+            hir::Uint(uint_ty) => return Primitive(uint_ty.into()),
+            hir::Float(float_ty) => return Primitive(float_ty.into()),
+        },
+        Res::SelfTy(..) if path.segments.len() == 1 => {
+            return Generic(kw::SelfUpper.to_string());
+        }
+        Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
+            return Generic(format!("{:#}", path.print()));
+        }
+        Res::SelfTy(..)
+        | Res::Def(DefKind::TyParam, _)
+        | Res::Def(DefKind::AssocTy, _) => true,
+        _ => false,
+    };
+    let did = register_res(&*cx, path.res);
+    ResolvedPath { path, param_names: None, did, is_generic }
+}
+
+pub fn get_auto_trait_and_blanket_impls(
+    cx: &DocContext<'tcx>,
+    ty: Ty<'tcx>,
+    param_env_def_id: DefId,
+) -> impl Iterator<Item = Item> {
+    AutoTraitFinder::new(cx).get_auto_trait_impls(ty, param_env_def_id).into_iter()
+        .chain(BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id))
+}
+
+pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId {
+    debug!("register_res({:?})", res);
+
+    let (did, kind) = match res {
+        Res::Def(DefKind::Fn, i) => (i, TypeKind::Function),
+        Res::Def(DefKind::TyAlias, i) => (i, TypeKind::Typedef),
+        Res::Def(DefKind::Enum, i) => (i, TypeKind::Enum),
+        Res::Def(DefKind::Trait, i) => (i, TypeKind::Trait),
+        Res::Def(DefKind::Struct, i) => (i, TypeKind::Struct),
+        Res::Def(DefKind::Union, i) => (i, TypeKind::Union),
+        Res::Def(DefKind::Mod, i) => (i, TypeKind::Module),
+        Res::Def(DefKind::ForeignTy, i) => (i, TypeKind::Foreign),
+        Res::Def(DefKind::Const, i) => (i, TypeKind::Const),
+        Res::Def(DefKind::Static, i) => (i, TypeKind::Static),
+        Res::Def(DefKind::Variant, i) => (cx.tcx.parent(i).expect("cannot get parent def id"),
+                            TypeKind::Enum),
+        Res::Def(DefKind::Macro(mac_kind), i) => match mac_kind {
+            MacroKind::Bang => (i, TypeKind::Macro),
+            MacroKind::Attr => (i, TypeKind::Attr),
+            MacroKind::Derive => (i, TypeKind::Derive),
+        },
+        Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias),
+        Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
+        Res::SelfTy(_, Some(impl_def_id)) => return impl_def_id,
+        _ => return res.def_id()
+    };
+    if did.is_local() { return did }
+    inline::record_extern_fqn(cx, did, kind);
+    if let TypeKind::Trait = kind {
+        inline::record_extern_trait(cx, did);
+    }
+    did
+}
+
+pub fn resolve_use_source(cx: &DocContext<'_>, path: Path) -> ImportSource {
+    ImportSource {
+        did: if path.res.opt_def_id().is_none() {
+            None
+        } else {
+            Some(register_res(cx, path.res))
+        },
+        path,
+    }
+}
+
+pub fn enter_impl_trait<F, R>(cx: &DocContext<'_>, f: F) -> R
+where
+    F: FnOnce() -> R,
+{
+    let old_bounds = mem::take(&mut *cx.impl_trait_bounds.borrow_mut());
+    let r = f();
+    assert!(cx.impl_trait_bounds.borrow().is_empty());
+    *cx.impl_trait_bounds.borrow_mut() = old_bounds;
+    r
+}
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index cdb1a1f..0db3d28 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -7,10 +7,10 @@
 use getopts;
 use rustc::lint::Level;
 use rustc::session;
-use rustc::session::config::{CrateType, parse_crate_types_from_list};
+use rustc::session::config::{CrateType, parse_crate_types_from_list, parse_externs};
 use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
 use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options,
-                             get_cmd_lint_options, host_triple, ExternEntry};
+                             get_cmd_lint_options, host_triple};
 use rustc::session::search_paths::SearchPath;
 use rustc_driver;
 use rustc_target::spec::TargetTriple;
@@ -320,13 +320,7 @@
         let libs = matches.opt_strs("L").iter()
             .map(|s| SearchPath::from_cli_opt(s, error_format))
             .collect();
-        let externs = match parse_externs(&matches) {
-            Ok(ex) => ex,
-            Err(err) => {
-                diag.struct_err(&err).emit();
-                return Err(1);
-            }
-        };
+        let externs = parse_externs(&matches, &debugging_options, error_format);
         let extern_html_root_urls = match parse_extern_html_roots(&matches) {
             Ok(ex) => ex,
             Err(err) => {
@@ -617,24 +611,3 @@
 
     Ok(externs)
 }
-
-/// Extracts `--extern CRATE=PATH` arguments from `matches` and
-/// returns a map mapping crate names to their paths or else an
-/// error message.
-/// Also handles `--extern-private` which for the purposes of rustdoc
-/// we can treat as `--extern`
-// FIXME(eddyb) This shouldn't be duplicated with `rustc::session`.
-fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> {
-    let mut externs: BTreeMap<_, ExternEntry> = BTreeMap::new();
-    for arg in matches.opt_strs("extern").iter().chain(matches.opt_strs("extern-private").iter()) {
-        let mut parts = arg.splitn(2, '=');
-        let name = parts.next().ok_or("--extern value must not be empty".to_string())?;
-        let location = parts.next().map(|s| s.to_string());
-        let name = name.to_string();
-        // For Rustdoc purposes, we can treat all externs as public
-        externs.entry(name)
-            .or_default()
-            .locations.insert(location.clone());
-    }
-    Ok(Externs::new(externs))
-}
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index b77b1c7..a524801 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -248,7 +248,9 @@
         ..
     } = options;
 
-    let extern_names: Vec<String> = externs.iter().map(|(s,_)| s).cloned().collect();
+    let extern_names: Vec<String> = externs.iter()
+        .filter(|(_, entry)| entry.add_prelude)
+        .map(|(name, _)| name).cloned().collect();
 
     // Add the doc cfg into the doc build.
     cfgs.push("doc".to_string());
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 4cde868..fd620d4 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -63,6 +63,13 @@
         }
     }
 
+    crate fn new() -> Buffer {
+        Buffer {
+            for_html: false,
+            buffer: String::new(),
+        }
+    }
+
     crate fn is_empty(&self) -> bool {
         self.buffer.is_empty()
     }
@@ -106,6 +113,10 @@
             write!(self, "{:#}", t);
         }
     }
+
+    crate fn is_for_html(&self) -> bool {
+        self.for_html
+    }
 }
 
 /// Wrapper struct for properly emitting a function or method declaration.
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index f5e4592..85f1323 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -1,7 +1,11 @@
 //! Item types.
 
 use std::fmt;
+
+use serde::{Serialize, Serializer};
+
 use syntax_pos::hygiene::MacroKind;
+
 use crate::clean;
 
 /// Item type. Corresponds to `clean::ItemEnum` variants.
@@ -45,6 +49,14 @@
     TraitAlias      = 25,
 }
 
+impl Serialize for ItemType {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        (*self as u8).serialize(serializer)
+    }
+}
 
 impl<'a> From<&'a clean::Item> for ItemType {
     fn from(item: &'a clean::Item) -> ItemType {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index b5c1a77..e764b7e 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -31,7 +31,8 @@
 use std::collections::{BTreeMap, VecDeque};
 use std::default::Default;
 use std::error;
-use std::fmt::{self, Formatter, Write as FmtWrite};
+
+use std::fmt::{self, Formatter, Write};
 use std::ffi::OsStr;
 use std::fs::{self, File};
 use std::io::prelude::*;
@@ -42,7 +43,8 @@
 use std::rc::Rc;
 
 use errors;
-use serialize::json::{ToJson, Json, as_json};
+use serde::{Serialize, Serializer};
+use serde::ser::SerializeSeq;
 use syntax::ast;
 use syntax::edition::Edition;
 use syntax::print::pprust;
@@ -303,19 +305,22 @@
     search_type: Option<IndexItemFunctionType>,
 }
 
-impl ToJson for IndexItem {
-    fn to_json(&self) -> Json {
+impl Serialize for IndexItem {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
         assert_eq!(self.parent.is_some(), self.parent_idx.is_some());
 
-        let mut data = Vec::with_capacity(6);
-        data.push((self.ty as usize).to_json());
-        data.push(self.name.to_json());
-        data.push(self.path.to_json());
-        data.push(self.desc.to_json());
-        data.push(self.parent_idx.to_json());
-        data.push(self.search_type.to_json());
-
-        Json::Array(data)
+        (
+            self.ty,
+            &self.name,
+            &self.path,
+            &self.desc,
+            self.parent_idx,
+            &self.search_type,
+        )
+            .serialize(serializer)
     }
 }
 
@@ -326,18 +331,20 @@
     generics: Option<Vec<String>>,
 }
 
-impl ToJson for Type {
-    fn to_json(&self) -> Json {
-        match self.name {
-            Some(ref name) => {
-                let mut data = Vec::with_capacity(2);
-                data.push(name.to_json());
-                if let Some(ref generics) = self.generics {
-                    data.push(generics.to_json());
-                }
-                Json::Array(data)
+impl Serialize for Type {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        if let Some(name) = &self.name {
+            let mut seq = serializer.serialize_seq(None)?;
+            seq.serialize_element(&name)?;
+            if let Some(generics) = &self.generics {
+                seq.serialize_element(&generics)?;
             }
-            None => Json::Null,
+            seq.end()
+        } else {
+            serializer.serialize_none()
         }
     }
 }
@@ -349,26 +356,29 @@
     output: Option<Vec<Type>>,
 }
 
-impl ToJson for IndexItemFunctionType {
-    fn to_json(&self) -> Json {
+impl Serialize for IndexItemFunctionType {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
         // If we couldn't figure out a type, just write `null`.
         let mut iter = self.inputs.iter();
         if match self.output {
             Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()),
             None => iter.any(|ref i| i.name.is_none()),
         } {
-            Json::Null
+            serializer.serialize_none()
         } else {
-            let mut data = Vec::with_capacity(2);
-            data.push(self.inputs.to_json());
-            if let Some(ref output) = self.output {
+            let mut seq = serializer.serialize_seq(None)?;
+            seq.serialize_element(&self.inputs)?;
+            if let Some(output) = &self.output {
                 if output.len() > 1 {
-                    data.push(output.to_json());
+                    seq.serialize_element(&output)?;
                 } else {
-                    data.push(output[0].to_json());
+                    seq.serialize_element(&output[0])?;
                 }
             }
-            Json::Array(data)
+            seq.end()
         }
     }
 }
@@ -596,7 +606,7 @@
     // To avoid theme switch latencies as much as possible, we put everything theme related
     // at the beginning of the html files into another js file.
     let theme_js = format!(
-r#"var themes = document.getElementById("theme-choices");
+        r#"var themes = document.getElementById("theme-choices");
 var themePicker = document.getElementById("theme-picker");
 
 function showThemeButtonState() {{
@@ -642,12 +652,11 @@
     }};
     but.onblur = handleThemeButtonsBlur;
     themes.appendChild(but);
-}});"#,
-                 as_json(&themes));
-    write(cx.dst.join(&format!("theme{}.js", cx.shared.resource_suffix)),
-          theme_js.as_bytes()
-    )?;
+}});"#, serde_json::to_string(&themes).unwrap());
 
+    write_minify(&cx.shared.fs, cx.path("theme.js"),
+                 &theme_js,
+                 options.enable_minification)?;
     write_minify(&cx.shared.fs, cx.path("main.js"),
                  static_files::MAIN_JS,
                  options.enable_minification)?;
@@ -715,19 +724,13 @@
         path: &Path,
         krate: &str,
         key: &str,
-        for_search_index: bool,
-    ) -> io::Result<(Vec<String>, Vec<String>, Vec<String>)> {
+    ) -> io::Result<(Vec<String>, Vec<String>)> {
         let mut ret = Vec::new();
         let mut krates = Vec::new();
-        let mut variables = Vec::new();
 
         if path.exists() {
             for line in BufReader::new(File::open(path)?).lines() {
                 let line = line?;
-                if for_search_index && line.starts_with("var R") {
-                    variables.push(line.clone());
-                    continue;
-                }
                 if !line.starts_with(key) {
                     continue;
                 }
@@ -741,7 +744,7 @@
                                                  .unwrap_or_else(|| String::new()));
             }
         }
-        Ok((ret, krates, variables))
+        Ok((ret, krates))
     }
 
     fn show_item(item: &IndexItem, krate: &str) -> String {
@@ -756,7 +759,7 @@
 
     let dst = cx.dst.join(&format!("aliases{}.js", cx.shared.resource_suffix));
     {
-        let (mut all_aliases, _, _) = try_err!(collect(&dst, &krate.name, "ALIASES", false), &dst);
+        let (mut all_aliases, _) = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst);
         let mut output = String::with_capacity(100);
         for (alias, items) in &cx.cache.aliases {
             if items.is_empty() {
@@ -853,9 +856,7 @@
         }
 
         let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix));
-        let (mut all_sources, _krates, _) = try_err!(collect(&dst, &krate.name, "sourcesIndex",
-                                                             false),
-                                                     &dst);
+        let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst);
         all_sources.push(format!("sourcesIndex[\"{}\"] = {};",
                                  &krate.name,
                                  hierarchy.to_json_string()));
@@ -867,23 +868,18 @@
 
     // Update the search index
     let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix));
-    let (mut all_indexes, mut krates, variables) = try_err!(collect(&dst,
-                                                                    &krate.name,
-                                                                    "searchIndex",
-                                                                    true), &dst);
+    let (mut all_indexes, mut krates) = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
     all_indexes.push(search_index);
 
     // Sort the indexes by crate so the file will be generated identically even
     // with rustdoc running in parallel.
     all_indexes.sort();
     {
-        let mut v = String::from("var N=null,E=\"\",T=\"t\",U=\"u\",searchIndex={};\n");
-        v.push_str(&minify_replacer(
-            &format!("{}\n{}", variables.join(""), all_indexes.join("\n")),
-            options.enable_minification));
+        let mut v = String::from("var searchIndex={};\n");
+        v.push_str(&all_indexes.join("\n"));
         // "addSearchOptions" has to be called first so the crate filtering can be set before the
         // search might start (if it's set into the URL for example).
-        v.push_str("addSearchOptions(searchIndex);initSearch(searchIndex);");
+        v.push_str("\naddSearchOptions(searchIndex);initSearch(searchIndex);");
         cx.shared.fs.write(&dst, &v)?;
     }
     if options.enable_index_page {
@@ -946,32 +942,48 @@
             }
         };
 
-        let mut have_impls = false;
-        let mut implementors = format!(r#"implementors["{}"] = ["#, krate.name);
-        for imp in imps {
-            // If the trait and implementation are in the same crate, then
-            // there's no need to emit information about it (there's inlining
-            // going on). If they're in different crates then the crate defining
-            // the trait will be interested in our implementation.
-            if imp.impl_item.def_id.krate == did.krate { continue }
-            // If the implementation is from another crate then that crate
-            // should add it.
-            if !imp.impl_item.def_id.is_local() { continue }
-            have_impls = true;
-            write!(implementors, "{{text:{},synthetic:{},types:{}}},",
-                   as_json(&imp.inner_impl().print().to_string()),
-                   imp.inner_impl().synthetic,
-                   as_json(&collect_paths_for_type(imp.inner_impl().for_.clone()))).unwrap();
+        #[derive(Serialize)]
+        struct Implementor {
+            text: String,
+            synthetic: bool,
+            types: Vec<String>,
         }
-        implementors.push_str("];");
+
+        let implementors = imps
+            .iter()
+            .filter_map(|imp| {
+                // If the trait and implementation are in the same crate, then
+                // there's no need to emit information about it (there's inlining
+                // going on). If they're in different crates then the crate defining
+                // the trait will be interested in our implementation.
+                //
+                // If the implementation is from another crate then that crate
+                // should add it.
+                if imp.impl_item.def_id.krate == did.krate || !imp.impl_item.def_id.is_local() {
+                    None
+                } else {
+                    Some(Implementor {
+                        text: imp.inner_impl().print().to_string(),
+                        synthetic: imp.inner_impl().synthetic,
+                        types: collect_paths_for_type(imp.inner_impl().for_.clone()),
+                    })
+                }
+            })
+            .collect::<Vec<_>>();
 
         // Only create a js file if we have impls to add to it. If the trait is
         // documented locally though we always create the file to avoid dead
         // links.
-        if !have_impls && !cx.cache.paths.contains_key(&did) {
+        if implementors.is_empty() && !cx.cache.paths.contains_key(&did) {
             continue;
         }
 
+        let implementors = format!(
+            r#"implementors["{}"] = {};"#,
+            krate.name,
+            serde_json::to_string(&implementors).unwrap()
+        );
+
         let mut mydst = dst.clone();
         for part in &remote_path[..remote_path.len() - 1] {
             mydst.push(part);
@@ -981,9 +993,8 @@
                             remote_item_type,
                             remote_path[remote_path.len() - 1]));
 
-        let (mut all_implementors, _, _) = try_err!(collect(&mydst, &krate.name, "implementors",
-                                                            false),
-                                                    &mydst);
+        let (mut all_implementors, _) = try_err!(collect(&mydst, &krate.name, "implementors"),
+                                                 &mydst);
         all_implementors.push(implementors);
         // Sort the implementors by crate so the file will be generated
         // identically even with rustdoc running in parallel.
@@ -1020,68 +1031,6 @@
     }
 }
 
-fn minify_replacer(
-    contents: &str,
-    enable_minification: bool,
-) -> String {
-    use minifier::js::{simple_minify, Keyword, ReservedChar, Token, Tokens};
-
-    if enable_minification {
-        let tokens: Tokens<'_> = simple_minify(contents)
-            .into_iter()
-            .filter(|(f, next)| {
-                // We keep backlines.
-                minifier::js::clean_token_except(f, next, &|c: &Token<'_>| {
-                    c.get_char() != Some(ReservedChar::Backline)
-                })
-            })
-            .map(|(f, _)| {
-                minifier::js::replace_token_with(f, &|t: &Token<'_>| {
-                    match *t {
-                        Token::Keyword(Keyword::Null) => Some(Token::Other("N")),
-                        Token::String(s) => {
-                            let s = &s[1..s.len() -1]; // The quotes are included
-                            if s.is_empty() {
-                                Some(Token::Other("E"))
-                            } else if s == "t" {
-                                Some(Token::Other("T"))
-                            } else if s == "u" {
-                                Some(Token::Other("U"))
-                            } else {
-                                None
-                            }
-                        }
-                        _ => None,
-                    }
-                })
-            })
-            .collect::<Vec<_>>()
-            .into();
-        let o = tokens.apply(|f| {
-            // We add a backline after the newly created variables.
-            minifier::js::aggregate_strings_into_array_with_separation_filter(
-                f,
-                "R",
-                Token::Char(ReservedChar::Backline),
-                // This closure prevents crates' names from being aggregated.
-                //
-                // The point here is to check if the string is preceded by '[' and
-                // "searchIndex". If so, it means this is a crate name and that it
-                // shouldn't be aggregated.
-                |tokens, pos| {
-                    pos < 2 ||
-                    !tokens[pos - 1].eq_char(ReservedChar::OpenBracket) ||
-                    tokens[pos - 2].get_other() != Some("searchIndex")
-                }
-            )
-        })
-        .to_string();
-        format!("{}\n", o)
-    } else {
-        format!("{}\n", contents)
-    }
-}
-
 #[derive(Debug, Eq, PartialEq, Hash)]
 struct ItemEntry {
     url: String,
@@ -1533,7 +1482,7 @@
             if !self.render_redirect_pages {
                 let items = self.build_sidebar_items(&m);
                 let js_dst = self.dst.join("sidebar-items.js");
-                let v = format!("initSidebarItems({});", as_json(&items));
+                let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap());
                 scx.fs.write(&js_dst, &v)?;
             }
 
@@ -2359,12 +2308,23 @@
 fn render_impls(cx: &Context, w: &mut Buffer,
                 traits: &[&&Impl],
                 containing_item: &clean::Item) {
-    for i in traits {
-        let did = i.trait_did().unwrap();
-        let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods);
-        render_impl(w, cx, i, assoc_link,
-                    RenderMode::Normal, containing_item.stable_since(), true, None, false, true);
-    }
+    let mut impls = traits.iter()
+        .map(|i| {
+            let did = i.trait_did().unwrap();
+            let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods);
+            let mut buffer = if w.is_for_html() {
+                Buffer::html()
+            } else {
+                Buffer::new()
+            };
+            render_impl(&mut buffer, cx, i, assoc_link,
+                        RenderMode::Normal, containing_item.stable_since(),
+                        true, None, false, true);
+            buffer.into_inner()
+        })
+        .collect::<Vec<_>>();
+    impls.sort();
+    w.write_str(&impls.join(""));
 }
 
 fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool) -> String {
@@ -2624,8 +2584,11 @@
             write_loading_content(w, "</div>");
         }
     }
-    write!(w, r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#,
-           as_json(&synthetic_types));
+    write!(
+        w,
+        r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#,
+        serde_json::to_string(&synthetic_types).unwrap(),
+    );
 
     write!(w, r#"<script type="text/javascript" async
                          src="{root_path}/implementors/{path}/{ty}.{name}.js">
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 65dd119..d80facf 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -8,7 +8,8 @@
 use std::collections::BTreeMap;
 use syntax::source_map::FileName;
 use syntax::symbol::sym;
-use serialize::json::{ToJson, Json, as_json};
+
+use serde::Serialize;
 
 use super::{ItemType, IndexItem, IndexItemFunctionType, Impl, shorten, plain_summary_line};
 use super::{Type, RenderInfo};
@@ -544,7 +545,7 @@
 fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     let mut nodeid_to_pathid = FxHashMap::default();
     let mut crate_items = Vec::with_capacity(cache.search_index.len());
-    let mut crate_paths = Vec::<Json>::new();
+    let mut crate_paths = vec![];
 
     let Cache { ref mut search_index,
                 ref orphan_impl_items,
@@ -581,7 +582,7 @@
                 lastpathid += 1;
 
                 let &(ref fqp, short) = paths.get(&nodeid).unwrap();
-                crate_paths.push(((short as usize), fqp.last().unwrap().clone()).to_json());
+                crate_paths.push((short, fqp.last().unwrap().clone()));
                 pathid
             }
         });
@@ -592,22 +593,33 @@
         } else {
             lastpath = item.path.clone();
         }
-        crate_items.push(item.to_json());
+        crate_items.push(&*item);
     }
 
     let crate_doc = krate.module.as_ref().map(|module| {
         shorten(plain_summary_line(module.doc_value()))
     }).unwrap_or(String::new());
 
-    let mut crate_data = BTreeMap::new();
-    crate_data.insert("doc".to_owned(), Json::String(crate_doc));
-    crate_data.insert("i".to_owned(), Json::Array(crate_items));
-    crate_data.insert("p".to_owned(), Json::Array(crate_paths));
+    #[derive(Serialize)]
+    struct CrateData<'a> {
+        doc: String,
+        #[serde(rename = "i")]
+        items: Vec<&'a IndexItem>,
+        #[serde(rename = "p")]
+        paths: Vec<(ItemType, String)>,
+    }
 
     // Collect the index into a string
-    format!("searchIndex[{}] = {};",
-            as_json(&krate.name),
-            Json::Object(crate_data))
+    format!(
+        r#"searchIndex["{}"] = {};"#,
+        krate.name,
+        serde_json::to_string(&CrateData {
+            doc: crate_doc,
+            items: crate_items,
+            paths: crate_paths,
+        })
+        .unwrap()
+    )
 }
 
 fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index cc0f470..49a9cb0 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1221,7 +1221,7 @@
                     // then an exact path match
                     path.indexOf(keys[i]) > -1 ||
                     // next if there is a parent, check for exact parent match
-                    (parent !== undefined &&
+                    (parent !== undefined && parent.name !== undefined &&
                         parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
                     // lastly check to see if the name was a levenshtein match
                     levenshtein(name, keys[i]) <= MAX_LEV_DISTANCE)) {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index be3644e..a7ef428 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -35,7 +35,6 @@
 extern crate rustc_target;
 extern crate rustc_typeck;
 extern crate rustc_lexer;
-extern crate serialize;
 extern crate syntax;
 extern crate syntax_expand;
 extern crate syntax_pos;
@@ -145,10 +144,6 @@
         stable("extern", |o| {
             o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]")
         }),
-        unstable("extern-private", |o| {
-            o.optmulti("", "extern-private",
-                       "pass an --extern to rustc (compatibility only)", "NAME=PATH")
-        }),
         unstable("extern-html-root-url", |o| {
             o.optmulti("", "extern-html-root-url",
                        "base URL to use for dependencies", "NAME=URL")
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 1f839f1..8db7bc1 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -54,7 +54,5 @@
         }
         println!("cargo:rustc-link-lib=c");
         println!("cargo:rustc-link-lib=compiler_rt");
-    } else if target.contains("hermit") {
-        println!("cargo:rustc-link-lib=hermit");
     }
 }
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index 522b8b2..e8b9e9c 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -433,7 +433,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub mod hash_map {
-    //! A hash map implemented with linear probing and Robin Hood bucket stealing.
+    //! A hash map implemented with quadratic probing and SIMD lookup.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::hash::map::*;
 }
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 6cf062d..b9cede7 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -495,11 +495,13 @@
     ///
     /// let os_str = OsStr::new("foo");
     /// ```
+    #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
         s.as_ref()
     }
 
+    #[inline]
     fn from_inner(inner: &Slice) -> &OsStr {
         unsafe { &*(inner as *const Slice as *const OsStr) }
     }
@@ -658,6 +660,7 @@
     ///
     /// Note: it is *crucial* that this API is private, to avoid
     /// revealing the internal, platform-specific encodings.
+    #[inline]
     fn bytes(&self) -> &[u8] {
         unsafe { &*(&self.inner as *const _ as *const [u8]) }
     }
@@ -797,6 +800,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq for OsStr {
+    #[inline]
     fn eq(&self, other: &OsStr) -> bool {
         self.bytes().eq(other.bytes())
     }
@@ -804,6 +808,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq<str> for OsStr {
+    #[inline]
     fn eq(&self, other: &str) -> bool {
         *self == *OsStr::new(other)
     }
@@ -811,6 +816,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq<OsStr> for str {
+    #[inline]
     fn eq(&self, other: &OsStr) -> bool {
         *other == *OsStr::new(self)
     }
@@ -944,6 +950,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<OsStr> for str {
+    #[inline]
     fn as_ref(&self) -> &OsStr {
         OsStr::from_inner(Slice::from_str(self))
     }
@@ -951,6 +958,7 @@
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<OsStr> for String {
+    #[inline]
     fn as_ref(&self) -> &OsStr {
         (&**self).as_ref()
     }
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index e5cf022..a109e38 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -2339,8 +2339,10 @@
         let filename = &tmpdir.join("file_that_does_not_exist.txt");
         let result = File::open(filename);
 
-        #[cfg(unix)]
+        #[cfg(all(unix, not(target_os = "vxworks")))]
         error!(result, "No such file or directory");
+        #[cfg(target_os = "vxworks")]
+        error!(result, "no such file or directory");
         #[cfg(windows)]
         error!(result, 2); // ERROR_FILE_NOT_FOUND
     }
@@ -2352,8 +2354,10 @@
 
         let result = fs::remove_file(filename);
 
-        #[cfg(unix)]
+        #[cfg(all(unix, not(target_os = "vxworks")))]
         error!(result, "No such file or directory");
+        #[cfg(target_os = "vxworks")]
+        error!(result, "no such file or directory");
         #[cfg(windows)]
         error!(result, 2); // ERROR_FILE_NOT_FOUND
     }
@@ -2553,7 +2557,10 @@
 
         check!(fs::set_permissions(filename, fs::Permissions::from_mode(0o1777)));
         let metadata1 = check!(fs::metadata(filename));
+        #[cfg(all(unix, not(target_os = "vxworks")))]
         assert_eq!(mask & metadata1.permissions().mode(), 0o1777);
+        #[cfg(target_os = "vxworks")]
+        assert_eq!(mask & metadata1.permissions().mode(), 0o0777);
     }
 
     #[test]
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index 6de3f1d..ac1ef3e 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -26,7 +26,6 @@
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
-#[cfg_attr(not(test), rustc_diagnostic_item = "gen_future")]
 struct GenFuture<T: Generator<Yield = ()>>(T);
 
 // We rely on the fact that async/await futures are immovable in order to create
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 20c1c5c..a1a33ba 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -987,7 +987,6 @@
     /// #![feature(io_slice_advance)]
     ///
     /// use std::io::IoSliceMut;
-    /// use std::mem;
     /// use std::ops::Deref;
     ///
     /// let mut buf1 = [1; 8];
@@ -1000,7 +999,7 @@
     /// ][..];
     ///
     /// // Mark 10 bytes as read.
-    /// bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 10);
+    /// bufs = IoSliceMut::advance(bufs, 10);
     /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
     /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
     /// ```
@@ -1090,20 +1089,19 @@
     /// #![feature(io_slice_advance)]
     ///
     /// use std::io::IoSlice;
-    /// use std::mem;
     /// use std::ops::Deref;
     ///
-    /// let mut buf1 = [1; 8];
-    /// let mut buf2 = [2; 16];
-    /// let mut buf3 = [3; 8];
+    /// let buf1 = [1; 8];
+    /// let buf2 = [2; 16];
+    /// let buf3 = [3; 8];
     /// let mut bufs = &mut [
-    ///     IoSlice::new(&mut buf1),
-    ///     IoSlice::new(&mut buf2),
-    ///     IoSlice::new(&mut buf3),
+    ///     IoSlice::new(&buf1),
+    ///     IoSlice::new(&buf2),
+    ///     IoSlice::new(&buf3),
     /// ][..];
     ///
     /// // Mark 10 bytes as written.
-    /// bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 10);
+    /// bufs = IoSlice::advance(bufs, 10);
     /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
     /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
     #[unstable(feature = "io_slice_advance", issue = "62726")]
@@ -2415,7 +2413,6 @@
     use crate::cmp;
     use crate::io::prelude::*;
     use crate::io::{self, IoSlice, IoSliceMut};
-    use crate::mem;
     use crate::ops::Deref;
 
     #[test]
@@ -2731,26 +2728,26 @@
         ][..];
 
         // Only in a single buffer..
-        bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 1);
+        bufs = IoSliceMut::advance(bufs, 1);
         assert_eq!(bufs[0].deref(), [1; 7].as_ref());
         assert_eq!(bufs[1].deref(), [2; 16].as_ref());
         assert_eq!(bufs[2].deref(), [3; 8].as_ref());
 
         // Removing a buffer, leaving others as is.
-        bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 7);
+        bufs = IoSliceMut::advance(bufs, 7);
         assert_eq!(bufs[0].deref(), [2; 16].as_ref());
         assert_eq!(bufs[1].deref(), [3; 8].as_ref());
 
         // Removing a buffer and removing from the next buffer.
-        bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 18);
+        bufs = IoSliceMut::advance(bufs, 18);
         assert_eq!(bufs[0].deref(), [3; 6].as_ref());
     }
 
     #[test]
     fn io_slice_mut_advance_empty_slice() {
-        let mut empty_bufs = &mut [][..];
+        let empty_bufs = &mut [][..];
         // Shouldn't panic.
-        IoSliceMut::advance(&mut empty_bufs, 1);
+        IoSliceMut::advance(empty_bufs, 1);
     }
 
     #[test]
@@ -2759,48 +2756,48 @@
         let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
 
         // Going beyond the total length should be ok.
-        bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 9);
+        bufs = IoSliceMut::advance(bufs, 9);
         assert!(bufs.is_empty());
     }
 
     #[test]
     fn io_slice_advance() {
-        let mut buf1 = [1; 8];
-        let mut buf2 = [2; 16];
-        let mut buf3 = [3; 8];
+        let buf1 = [1; 8];
+        let buf2 = [2; 16];
+        let buf3 = [3; 8];
         let mut bufs =
-            &mut [IoSlice::new(&mut buf1), IoSlice::new(&mut buf2), IoSlice::new(&mut buf3)][..];
+            &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..];
 
         // Only in a single buffer..
-        bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 1);
+        bufs = IoSlice::advance(bufs, 1);
         assert_eq!(bufs[0].deref(), [1; 7].as_ref());
         assert_eq!(bufs[1].deref(), [2; 16].as_ref());
         assert_eq!(bufs[2].deref(), [3; 8].as_ref());
 
         // Removing a buffer, leaving others as is.
-        bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 7);
+        bufs = IoSlice::advance(bufs, 7);
         assert_eq!(bufs[0].deref(), [2; 16].as_ref());
         assert_eq!(bufs[1].deref(), [3; 8].as_ref());
 
         // Removing a buffer and removing from the next buffer.
-        bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 18);
+        bufs = IoSlice::advance(bufs, 18);
         assert_eq!(bufs[0].deref(), [3; 6].as_ref());
     }
 
     #[test]
     fn io_slice_advance_empty_slice() {
-        let mut empty_bufs = &mut [][..];
+        let empty_bufs = &mut [][..];
         // Shouldn't panic.
-        IoSlice::advance(&mut empty_bufs, 1);
+        IoSlice::advance(empty_bufs, 1);
     }
 
     #[test]
     fn io_slice_advance_beyond_total_length() {
-        let mut buf1 = [1; 8];
-        let mut bufs = &mut [IoSlice::new(&mut buf1)][..];
+        let buf1 = [1; 8];
+        let mut bufs = &mut [IoSlice::new(&buf1)][..];
 
         // Going beyond the total length should be ok.
-        bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 9);
+        bufs = IoSlice::advance(bufs, 9);
         assert!(bufs.is_empty());
     }
 }
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index 5b7bef9..de7ced3 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -57,7 +57,7 @@
 /// 'outer: for i in 1..=5 {
 ///     println!("outer iteration (i): {}", i);
 ///
-///     'inner: for j in 1..=200 {
+///     '_inner: for j in 1..=200 {
 ///         println!("    inner iteration (j): {}", j);
 ///         if j >= 3 {
 ///             // breaks from inner loop, let's outer loop continue.
@@ -178,7 +178,7 @@
 ///```rust
 /// // Print Odd numbers under 30 with unit <= 5
 /// 'tens: for ten in 0..3 {
-///     'units: for unit in 0..=9 {
+///     '_units: for unit in 0..=9 {
 ///         if unit % 2 == 0 {
 ///             continue;
 ///         }
diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs
index 8106d1c..686fa8c 100644
--- a/src/libstd/net/parser.rs
+++ b/src/libstd/net/parser.rs
@@ -44,19 +44,6 @@
         self.read_atomically(move |p| cb(p).filter(|_| p.is_eof()))
     }
 
-    // Return result of first successful parser
-    fn read_or<T>(
-        &mut self,
-        parsers: &mut [Box<dyn FnMut(&mut Parser<'_>) -> Option<T> + 'static>],
-    ) -> Option<T> {
-        for pf in parsers {
-            if let Some(r) = self.read_atomically(|p: &mut Parser<'_>| pf(p)) {
-                return Some(r);
-            }
-        }
-        None
-    }
-
     // Apply 3 parsers sequentially
     fn read_seq_3<A, B, C, PA, PB, PC>(&mut self, pa: PA, pb: PB, pc: PC) -> Option<(A, B, C)>
     where
@@ -235,9 +222,8 @@
     }
 
     fn read_ip_addr(&mut self) -> Option<IpAddr> {
-        let ipv4_addr = |p: &mut Parser<'_>| p.read_ipv4_addr().map(IpAddr::V4);
-        let ipv6_addr = |p: &mut Parser<'_>| p.read_ipv6_addr().map(IpAddr::V6);
-        self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
+        self.read_ipv4_addr().map(IpAddr::V4)
+            .or_else(|| self.read_ipv6_addr().map(IpAddr::V6))
     }
 
     fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
@@ -268,9 +254,8 @@
     }
 
     fn read_socket_addr(&mut self) -> Option<SocketAddr> {
-        let v4 = |p: &mut Parser<'_>| p.read_socket_addr_v4().map(SocketAddr::V4);
-        let v6 = |p: &mut Parser<'_>| p.read_socket_addr_v6().map(SocketAddr::V6);
-        self.read_or(&mut [Box::new(v4), Box::new(v6)])
+        self.read_socket_addr_v4().map(SocketAddr::V4)
+            .or_else(|| self.read_socket_addr_v6().map(SocketAddr::V6))
     }
 }
 
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 87c2318..e90da69 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -143,10 +143,8 @@
 #[must_use = "if unused the Mutex will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct MutexGuard<'a, T: ?Sized + 'a> {
-    // funny underscores due to how Deref/DerefMut currently work (they
-    // disregard field privacy).
-    __lock: &'a Mutex<T>,
-    __poison: poison::Guard,
+    lock: &'a Mutex<T>,
+    poison: poison::Guard,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -417,8 +415,8 @@
     unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> {
         poison::map_result(lock.poison.borrow(), |guard| {
             MutexGuard {
-                __lock: lock,
-                __poison: guard,
+                lock: lock,
+                poison: guard,
             }
         })
     }
@@ -429,14 +427,14 @@
     type Target = T;
 
     fn deref(&self) -> &T {
-        unsafe { &*self.__lock.data.get() }
+        unsafe { &*self.lock.data.get() }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
     fn deref_mut(&mut self) -> &mut T {
-        unsafe { &mut *self.__lock.data.get() }
+        unsafe { &mut *self.lock.data.get() }
     }
 }
 
@@ -445,8 +443,8 @@
     #[inline]
     fn drop(&mut self) {
         unsafe {
-            self.__lock.poison.done(&self.__poison);
-            self.__lock.inner.raw_unlock();
+            self.lock.poison.done(&self.poison);
+            self.lock.inner.raw_unlock();
         }
     }
 }
@@ -466,11 +464,11 @@
 }
 
 pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
-    &guard.__lock.inner
+    &guard.lock.inner
 }
 
 pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
-    &guard.__lock.poison
+    &guard.lock.poison
 }
 
 #[cfg(all(test, not(target_os = "emscripten")))]
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index b1b56f3..c217291 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -87,7 +87,7 @@
 #[must_use = "if unused the RwLock will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
-    __lock: &'a RwLock<T>,
+    lock: &'a RwLock<T>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -108,8 +108,8 @@
 #[must_use = "if unused the RwLock will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
-    __lock: &'a RwLock<T>,
-    __poison: poison::Guard,
+    lock: &'a RwLock<T>,
+    poison: poison::Guard,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -465,7 +465,7 @@
                   -> LockResult<RwLockReadGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |_| {
             RwLockReadGuard {
-                __lock: lock,
+                lock: lock,
             }
         })
     }
@@ -476,8 +476,8 @@
                   -> LockResult<RwLockWriteGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |guard| {
             RwLockWriteGuard {
-                __lock: lock,
-                __poison: guard,
+                lock: lock,
+                poison: guard,
             }
         })
     }
@@ -487,7 +487,7 @@
 impl<T: fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("RwLockReadGuard")
-            .field("lock", &self.__lock)
+            .field("lock", &self.lock)
             .finish()
     }
 }
@@ -503,7 +503,7 @@
 impl<T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("RwLockWriteGuard")
-            .field("lock", &self.__lock)
+            .field("lock", &self.lock)
             .finish()
     }
 }
@@ -520,7 +520,7 @@
     type Target = T;
 
     fn deref(&self) -> &T {
-        unsafe { &*self.__lock.data.get() }
+        unsafe { &*self.lock.data.get() }
     }
 }
 
@@ -529,29 +529,29 @@
     type Target = T;
 
     fn deref(&self) -> &T {
-        unsafe { &*self.__lock.data.get() }
+        unsafe { &*self.lock.data.get() }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
     fn deref_mut(&mut self) -> &mut T {
-        unsafe { &mut *self.__lock.data.get() }
+        unsafe { &mut *self.lock.data.get() }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
     fn drop(&mut self) {
-        unsafe { self.__lock.inner.read_unlock(); }
+        unsafe { self.lock.inner.read_unlock(); }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
     fn drop(&mut self) {
-        self.__lock.poison.done(&self.__poison);
-        unsafe { self.__lock.inner.write_unlock(); }
+        self.lock.poison.done(&self.poison);
+        unsafe { self.lock.inner.write_unlock(); }
     }
 }
 
diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs
index dfb9307..0861432 100644
--- a/src/libstd/sys/unix/fast_thread_local.rs
+++ b/src/libstd/sys/unix/fast_thread_local.rs
@@ -8,8 +8,6 @@
 // Note, however, that we run on lots older linuxes, as well as cross
 // compiling from a newer linux to an older linux, so we also have a
 // fallback implementation to use as well.
-//
-// Due to rust-lang/rust#18804, make sure this is not generic!
 #[cfg(any(
     target_os = "linux",
     target_os = "fuchsia",
diff --git a/src/libstd/sys/vxworks/ext/mod.rs b/src/libstd/sys/vxworks/ext/mod.rs
index 251a198..8fa9bd9 100644
--- a/src/libstd/sys/vxworks/ext/mod.rs
+++ b/src/libstd/sys/vxworks/ext/mod.rs
@@ -18,4 +18,7 @@
     #[doc(no_inline)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+    #[doc(no_inline)]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::process::ExitStatusExt;
 }
diff --git a/src/libstd/sys/vxworks/os.rs b/src/libstd/sys/vxworks/os.rs
index baa6c42..71e1d16 100644
--- a/src/libstd/sys/vxworks/os.rs
+++ b/src/libstd/sys/vxworks/os.rs
@@ -11,14 +11,12 @@
 use crate::ptr;
 use crate::slice;
 use crate::str;
-use crate::sys_common::mutex::Mutex;
+use crate::sys_common::mutex::{Mutex, MutexGuard};
 use crate::sys::cvt;
 /*use sys::fd; this one is probably important */
 use crate::vec;
 
 const TMPBUF_SZ: usize = 128;
-static ENV_LOCK: Mutex = Mutex::new();
-
 
 // This is a terrible fix
 use crate::sys::os_str::Buf;
@@ -200,11 +198,18 @@
     &mut environ
 }
 
+pub unsafe fn env_lock() -> MutexGuard<'static> {
+    // We never call `ENV_LOCK.init()`, so it is UB to attempt to
+    // acquire this mutex reentrantly!
+    static ENV_LOCK: Mutex = Mutex::new();
+    ENV_LOCK.lock()
+}
+
 /// Returns a vector of (variable, value) byte-vector pairs for all the
 /// environment variables of the current process.
 pub fn env() -> Env {
     unsafe {
-        let _guard = ENV_LOCK.lock();
+        let _guard = env_lock();
         let mut environ = *environ();
         if environ == ptr::null() {
             panic!("os::env() failure getting env string from OS: {}",
@@ -244,7 +249,7 @@
     // always None as well
     let k = CString::new(k.as_bytes())?;
     unsafe {
-        let _guard = ENV_LOCK.lock();
+        let _guard = env_lock();
         let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
         let ret = if s.is_null() {
             None
@@ -260,7 +265,7 @@
     let v = CString::new(v.as_bytes())?;
 
     unsafe {
-        let _guard = ENV_LOCK.lock();
+        let _guard = env_lock();
         cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
     }
 }
@@ -269,7 +274,7 @@
     let nbuf = CString::new(n.as_bytes())?;
 
     unsafe {
-        let _guard = ENV_LOCK.lock();
+        let _guard = env_lock();
         cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
     }
 }
diff --git a/src/libstd/sys/vxworks/process/process_vxworks.rs b/src/libstd/sys/vxworks/process/process_vxworks.rs
index 7446471..79bfd770 100644
--- a/src/libstd/sys/vxworks/process/process_vxworks.rs
+++ b/src/libstd/sys/vxworks/process/process_vxworks.rs
@@ -15,6 +15,7 @@
                  -> io::Result<(Process, StdioPipes)> {
         use crate::sys::{cvt_r};
         const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
+        let envp = self.capture_env();
 
         if self.saw_nul() {
             return Err(io::Error::new(ErrorKind::InvalidInput,
@@ -52,12 +53,19 @@
                 t!(cvt(libc::chdir(cwd.as_ptr())));
             }
 
+            let c_envp = envp.as_ref().map(|c| c.as_ptr())
+                .unwrap_or_else(|| *sys::os::environ() as *const _);
+            let stack_size = thread::min_stack();
+
+            // ensure that access to the environment is synchronized
+            let _lock = sys::os::env_lock();
+
             let ret = libc::rtpSpawn(
                 self.get_argv()[0],                   // executing program
                 self.get_argv().as_ptr() as *mut *const c_char, // argv
-                *sys::os::environ() as *mut *const c_char,
+                c_envp as *mut *const c_char,
                 100 as c_int,                         // initial priority
-                thread::min_stack(),                  // initial stack size.
+                stack_size,                           // initial stack size.
                 0,                                    // options
                 0                                     // task options
             );
diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs
index 3db36f5..02aa68d 100644
--- a/src/libstd/sys/wasi/args.rs
+++ b/src/libstd/sys/wasi/args.rs
@@ -26,6 +26,7 @@
         let mut argv = Vec::with_capacity(argc);
         let mut buf = Vec::with_capacity(buf_size);
         wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
+        argv.set_len(argc);
         let mut ret = Vec::with_capacity(argc);
         for ptr in argv {
             let s = CStr::from_ptr(ptr.cast());
diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs
index 32f4011..2f2f285 100644
--- a/src/libstd/sys/windows/net.rs
+++ b/src/libstd/sys/windows/net.rs
@@ -100,7 +100,7 @@
                                 c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
                 c::INVALID_SOCKET => {
                     match c::WSAGetLastError() {
-                        c::WSAEPROTOTYPE => {
+                        c::WSAEPROTOTYPE | c::WSAEINVAL => {
                             match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0,
                                                 c::WSA_FLAG_OVERLAPPED) {
                                 c::INVALID_SOCKET => Err(last_error()),
@@ -199,7 +199,7 @@
                                 c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
                 c::INVALID_SOCKET => {
                     match c::WSAGetLastError() {
-                        c::WSAEPROTOTYPE => {
+                        c::WSAEPROTOTYPE | c::WSAEINVAL => {
                             match c::WSASocketW(info.iAddressFamily,
                                                 info.iSocketType,
                                                 info.iProtocol,
diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs
index e451e0c..ef260f9 100644
--- a/src/libstd/sys/windows/os_str.rs
+++ b/src/libstd/sys/windows/os_str.rs
@@ -128,6 +128,7 @@
 }
 
 impl Slice {
+    #[inline]
     pub fn from_str(s: &str) -> &Slice {
         unsafe { mem::transmute(Wtf8::from_str(s)) }
     }
diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs
index a2608ad..eb8a881 100644
--- a/src/libstd/sys_common/os_str_bytes.rs
+++ b/src/libstd/sys_common/os_str_bytes.rs
@@ -139,10 +139,12 @@
 }
 
 impl Slice {
+    #[inline]
     fn from_u8_slice(s: &[u8]) -> &Slice {
         unsafe { mem::transmute(s) }
     }
 
+    #[inline]
     pub fn from_str(s: &str) -> &Slice {
         Slice::from_u8_slice(s.as_bytes())
     }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 75ddf10..92ba071 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2488,14 +2488,14 @@
 ///
 /// The name might be a dummy name in case of anonymous items.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct Item {
+pub struct Item<K = ItemKind> {
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
     pub ident: Ident,
 
-    pub kind: ItemKind,
+    pub kind: K,
 
     /// Original tokens this item was parsed from. This isn't necessarily
     /// available for all items, although over time more and more items should
@@ -2650,16 +2650,7 @@
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct ForeignItem {
-    pub attrs: Vec<Attribute>,
-    pub id: NodeId,
-    pub span: Span,
-    pub vis: Visibility,
-    pub ident: Ident,
-
-    pub kind: ForeignItemKind,
-}
+pub type ForeignItem = Item<ForeignItemKind>;
 
 /// An item within an `extern` block.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index a947426..3617380 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -7,6 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
 
+#![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(const_fn)]
 #![feature(const_transmute)]
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 8889e5d..f8795d8 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -1053,7 +1053,7 @@
 pub fn noop_flat_map_foreign_item<T: MutVisitor>(mut item: ForeignItem, visitor: &mut T)
     -> SmallVec<[ForeignItem; 1]>
 {
-    let ForeignItem { ident, attrs, kind, id, span, vis } = &mut item;
+    let ForeignItem { ident, attrs, id, kind, vis, span, tokens: _ } = &mut item;
     visitor.visit_ident(ident);
     visit_attrs(attrs, visitor);
     match kind {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 4821bbd..f0c5fb3 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -317,7 +317,7 @@
 }
 
 fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String {
-    let convert_dollar_crate = if convert_dollar_crate { Some(token.span) } else { None };
+    let convert_dollar_crate = convert_dollar_crate.then_some(token.span);
     token_kind_to_string_ext(&token.kind, convert_dollar_crate)
 }
 
@@ -1518,6 +1518,7 @@
 
     crate fn print_variant(&mut self, v: &ast::Variant) {
         self.head("");
+        self.print_visibility(&v.vis);
         let generics = ast::Generics::default();
         self.print_struct(&v.data, &generics, v.ident, v.span, false);
         match v.disr_expr {
diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs
index 4127a8c..efb3c23 100644
--- a/src/libsyntax/util/lev_distance.rs
+++ b/src/libsyntax/util/lev_distance.rs
@@ -77,6 +77,6 @@
     if let Some(candidate) = case_insensitive_match {
         Some(candidate) // exact case insensitive match has a higher priority
     } else {
-        if let Some((candidate, _)) = levenstein_match { Some(candidate) } else { None }
+        levenstein_match.map(|(candidate, _)| candidate)
     }
 }
diff --git a/src/libsyntax_expand/mbe/macro_parser.rs b/src/libsyntax_expand/mbe/macro_parser.rs
index bf7960f..1e2f3f9 100644
--- a/src/libsyntax_expand/mbe/macro_parser.rs
+++ b/src/libsyntax_expand/mbe/macro_parser.rs
@@ -83,7 +83,7 @@
 use syntax::sess::ParseSess;
 use syntax::symbol::{kw, sym, Symbol};
 use syntax::token::{self, DocComment, Nonterminal, Token};
-use syntax::tokenstream::{DelimSpan, TokenStream};
+use syntax::tokenstream::TokenStream;
 
 use errors::{PResult, FatalError};
 use smallvec::{smallvec, SmallVec};
@@ -164,11 +164,6 @@
     /// The position of the "dot" in this matcher
     idx: usize,
 
-    /// The first span of source that the beginning of this matcher corresponds to. In other
-    /// words, the token in the source whose span is `sp_open` is matched against the first token of
-    /// the matcher.
-    sp_open: Span,
-
     /// For each named metavar in the matcher, we keep track of token trees matched against the
     /// metavar by the black box parser. In particular, there may be more than one match per
     /// metavar if we are in a repetition (each repetition matches each of the variables).
@@ -307,8 +302,8 @@
 }
 
 /// Generates the top-level matcher position in which the "dot" is before the first token of the
-/// matcher `ms` and we are going to start matching at the span `open` in the source.
-fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree], open: Span) -> MatcherPos<'root, 'tt> {
+/// matcher `ms`.
+fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree]) -> MatcherPos<'root, 'tt> {
     let match_idx_hi = count_names(ms);
     let matches = create_matches(match_idx_hi);
     MatcherPos {
@@ -316,8 +311,6 @@
         top_elts: TtSeq(ms), // "elts" is an abbr. for "elements"
         // The "dot" is before the first token of the matcher
         idx: 0,
-        // We start matching at the span `open` in the source code
-        sp_open: open,
 
         // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in `top_elts`.
         // `match_lo` for `top_elts` is 0 and `match_hi` is `matches.len()`. `match_cur` is 0 since
@@ -355,7 +348,7 @@
 /// token tree it was derived from.
 #[derive(Debug, Clone)]
 crate enum NamedMatch {
-    MatchedSeq(Lrc<NamedMatchVec>, DelimSpan),
+    MatchedSeq(Lrc<NamedMatchVec>),
     MatchedNonterminal(Lrc<Nonterminal>),
 }
 
@@ -497,8 +490,7 @@
                     // Add matches from this repetition to the `matches` of `up`
                     for idx in item.match_lo..item.match_hi {
                         let sub = item.matches[idx].clone();
-                        let span = DelimSpan::from_pair(item.sp_open, token.span);
-                        new_pos.push_match(idx, MatchedSeq(sub, span));
+                        new_pos.push_match(idx, MatchedSeq(sub));
                     }
 
                     // Move the "dot" past the repetition in `up`
@@ -552,7 +544,7 @@
                         new_item.match_cur += seq.num_captures;
                         new_item.idx += 1;
                         for idx in item.match_cur..item.match_cur + seq.num_captures {
-                            new_item.push_match(idx, MatchedSeq(Lrc::new(smallvec![]), sp));
+                            new_item.push_match(idx, MatchedSeq(Lrc::new(smallvec![])));
                         }
                         cur_items.push(new_item);
                     }
@@ -568,7 +560,6 @@
                         match_cur: item.match_cur,
                         match_hi: item.match_cur + seq.num_captures,
                         up: Some(item),
-                        sp_open: sp.open,
                         top_elts: Tt(TokenTree::Sequence(sp, seq)),
                     })));
                 }
@@ -663,7 +654,7 @@
     //
     // This MatcherPos instance is allocated on the stack. All others -- and
     // there are frequently *no* others! -- are allocated on the heap.
-    let mut initial = initial_matcher_pos(ms, parser.token.span);
+    let mut initial = initial_matcher_pos(ms);
     let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)];
     let mut next_items = Vec::new();
 
diff --git a/src/libsyntax_expand/mbe/macro_rules.rs b/src/libsyntax_expand/mbe/macro_rules.rs
index e3c3655..2dd1587 100644
--- a/src/libsyntax_expand/mbe/macro_rules.rs
+++ b/src/libsyntax_expand/mbe/macro_rules.rs
@@ -379,7 +379,7 @@
 
     // Extract the arguments:
     let lhses = match argument_map[&lhs_nm] {
-        MatchedSeq(ref s, _) => s
+        MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
                 if let MatchedNonterminal(ref nt) = *m {
@@ -402,7 +402,7 @@
     };
 
     let rhses = match argument_map[&rhs_nm] {
-        MatchedSeq(ref s, _) => s
+        MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
                 if let MatchedNonterminal(ref nt) = *m {
diff --git a/src/libsyntax_expand/mbe/transcribe.rs b/src/libsyntax_expand/mbe/transcribe.rs
index a115766..0605f7f 100644
--- a/src/libsyntax_expand/mbe/transcribe.rs
+++ b/src/libsyntax_expand/mbe/transcribe.rs
@@ -299,7 +299,7 @@
         for &(idx, _) in repeats {
             match matched {
                 MatchedNonterminal(_) => break,
-                MatchedSeq(ref ads, _) => matched = ads.get(idx).unwrap(),
+                MatchedSeq(ref ads) => matched = ads.get(idx).unwrap(),
             }
         }
 
@@ -382,7 +382,7 @@
             match lookup_cur_matched(name, interpolations, repeats) {
                 Some(matched) => match matched {
                     MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
-                    MatchedSeq(ref ads, _) => LockstepIterSize::Constraint(ads.len(), name),
+                    MatchedSeq(ref ads) => LockstepIterSize::Constraint(ads.len(), name),
                 },
                 _ => LockstepIterSize::Unconstrained,
             }
diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs
index 74ade1d..faea04e 100644
--- a/src/libsyntax_expand/placeholders.rs
+++ b/src/libsyntax_expand/placeholders.rs
@@ -65,6 +65,7 @@
             AstFragment::ForeignItems(smallvec![ast::ForeignItem {
                 id, span, ident, vis, attrs,
                 kind: ast::ForeignItemKind::Macro(mac_placeholder()),
+                tokens: None,
             }]),
         AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
             id, span, kind: ast::PatKind::Mac(mac_placeholder()),
diff --git a/src/libsyntax_expand/proc_macro.rs b/src/libsyntax_expand/proc_macro.rs
index 8e56e2b..520488c 100644
--- a/src/libsyntax_expand/proc_macro.rs
+++ b/src/libsyntax_expand/proc_macro.rs
@@ -1,7 +1,7 @@
 use crate::base::{self, *};
 use crate::proc_macro_server;
 
-use syntax::ast::{self, ItemKind, MacArgs};
+use syntax::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
 use syntax::errors::{Applicability, FatalError};
 use syntax::symbol::sym;
 use syntax::token;
@@ -171,34 +171,71 @@
         if !attr.has_name(sym::derive) {
             return true;
         }
-        if !attr.is_meta_item_list() {
-            cx.struct_span_err(attr.span, "malformed `derive` attribute input")
-                .span_suggestion(
-                    attr.span,
-                    "missing traits to be derived",
-                    "#[derive(Trait1, Trait2, ...)]".to_owned(),
-                    Applicability::HasPlaceholders,
-                ).emit();
-            return false;
-        }
 
-        let parse_derive_paths = |attr: &ast::Attribute| {
-            if let MacArgs::Empty = attr.get_normal_item().args {
-                return Ok(Vec::new());
+        // 1) First let's ensure that it's a meta item.
+        let nmis = match attr.meta_item_list() {
+            None => {
+                cx.struct_span_err(attr.span, "malformed `derive` attribute input")
+                    .span_suggestion(
+                        attr.span,
+                        "missing traits to be derived",
+                        "#[derive(Trait1, Trait2, ...)]".to_owned(),
+                        Applicability::HasPlaceholders,
+                    )
+                    .emit();
+                return false;
             }
-            rustc_parse::parse_in_attr(cx.parse_sess, attr, |p| p.parse_derive_paths())
+            Some(x) => x,
         };
 
-        match parse_derive_paths(attr) {
-            Ok(traits) => {
-                result.extend(traits);
-                true
-            }
-            Err(mut e) => {
-                e.emit();
-                false
-            }
-        }
+        let mut error_reported_filter_map = false;
+        let mut error_reported_map = false;
+        let traits = nmis
+            .into_iter()
+            // 2) Moreover, let's ensure we have a path and not `#[derive("foo")]`.
+            .filter_map(|nmi| match nmi {
+                NestedMetaItem::Literal(lit) => {
+                    error_reported_filter_map = true;
+                    cx.struct_span_err(lit.span, "expected path to a trait, found literal")
+                        .help("for example, write `#[derive(Debug)]` for `Debug`")
+                        .emit();
+                    None
+                }
+                NestedMetaItem::MetaItem(mi) => Some(mi),
+            })
+            // 3) Finally, we only accept `#[derive($path_0, $path_1, ..)]`
+            // but not e.g. `#[derive($path_0 = "value", $path_1(abc))]`.
+            // In this case we can still at least determine that the user
+            // wanted this trait to be derived, so let's keep it.
+            .map(|mi| {
+                let mut traits_dont_accept = |title, action| {
+                    error_reported_map = true;
+                    let sp = mi.span.with_lo(mi.path.span.hi());
+                    cx.struct_span_err(sp, title)
+                        .span_suggestion(
+                            sp,
+                            action,
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        )
+                        .emit();
+                };
+                match &mi.kind {
+                    MetaItemKind::List(..) => traits_dont_accept(
+                        "traits in `#[derive(...)]` don't accept arguments",
+                        "remove the arguments",
+                    ),
+                    MetaItemKind::NameValue(..) => traits_dont_accept(
+                        "traits in `#[derive(...)]` don't accept values",
+                        "remove the value",
+                    ),
+                    MetaItemKind::Word => {}
+                }
+                mi.path
+            });
+
+        result.extend(traits);
+        !error_reported_filter_map && !error_reported_map
     });
     result
 }
diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs
index 3d4f827..0d1d292 100644
--- a/src/libsyntax_ext/format_foreign.rs
+++ b/src/libsyntax_ext/format_foreign.rs
@@ -95,12 +95,12 @@
             };
 
             // Has a special form in Rust for numbers.
-            let fill = if c_zero { Some("0") } else { None };
+            let fill = c_zero.then_some("0");
 
-            let align = if c_left { Some("<") } else { None };
+            let align = c_left.then_some("<");
 
             // Rust doesn't have an equivalent to the `' '` flag.
-            let sign = if c_plus { Some("+") } else { None };
+            let sign = c_plus.then_some("+");
 
             // Not *quite* the same, depending on the type...
             let alt = c_alt;
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index b9287d2..55c7f3f 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -3,6 +3,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(nll)]
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 2af6671..92de56b 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -213,6 +213,7 @@
         const_indexing,
         const_in_array_repeat_expressions,
         const_let,
+        const_mut_refs,
         const_panic,
         const_raw_ptr_deref,
         const_raw_ptr_to_usize_cast,
@@ -659,6 +660,7 @@
         _Self,
         self_in_typedefs,
         self_struct_ctor,
+        send_trait,
         should_panic,
         simd,
         simd_extract,
@@ -696,6 +698,7 @@
         sty,
         sub_with_overflow,
         suggestion,
+        sync_trait,
         target_feature,
         target_has_atomic,
         target_has_atomic_load_store,
@@ -869,12 +872,18 @@
 
 impl fmt::Debug for Ident {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self.is_raw_guess() {
+            write!(f, "r#")?;
+        }
         write!(f, "{}{:?}", self.name, self.span.ctxt())
     }
 }
 
 impl fmt::Display for Ident {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self.is_raw_guess() {
+            write!(f, "r#")?;
+        }
         fmt::Display::fmt(&self.name, f)
     }
 }
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 7647978..0097558 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -24,6 +24,7 @@
 #![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
 #![feature(rustc_private)]
 #![feature(nll)]
+#![feature(bool_to_option)]
 #![feature(set_stdio)]
 #![feature(panic_unwind)]
 #![feature(staged_api)]
@@ -562,11 +563,7 @@
         None
     };
 
-    let start = if report_time {
-        Some(Instant::now())
-    } else {
-        None
-    };
+    let start = report_time.then(Instant::now);
     let result = catch_unwind(AssertUnwindSafe(testfn));
     let exec_time = start.map(|start| {
         let duration = start.elapsed();
@@ -597,11 +594,7 @@
         let args = env::args().collect::<Vec<_>>();
         let current_exe = &args[0];
 
-        let start = if report_time {
-            Some(Instant::now())
-        } else {
-            None
-        };
+        let start = report_time.then(Instant::now);
         let output = match Command::new(current_exe)
             .env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice())
             .output() {
diff --git a/src/llvm-project b/src/llvm-project
index de1a7db..2cb4100 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit de1a7dbf6c6b34f56e65732d45970ff27a8e84bf
+Subproject commit 2cb41005ed5c4747b10d2bf01d8779d3bb4ae32d
diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml
index 997d139..86a93d7 100644
--- a/src/rustc/Cargo.toml
+++ b/src/rustc/Cargo.toml
@@ -23,3 +23,4 @@
 
 [features]
 jemalloc = ['jemalloc-sys']
+llvm = ['rustc_driver/llvm']
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 1cb123e..6698e5d 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -658,46 +658,11 @@
   }
 };
 
-class RustPrintModulePass : public ModulePass {
-  raw_ostream* OS;
-  DemangleFn Demangle;
-public:
-  static char ID;
-  RustPrintModulePass() : ModulePass(ID), OS(nullptr), Demangle(nullptr) {}
-  RustPrintModulePass(raw_ostream &OS, DemangleFn Demangle)
-      : ModulePass(ID), OS(&OS), Demangle(Demangle) {}
-
-  bool runOnModule(Module &M) override {
-    RustAssemblyAnnotationWriter AW(Demangle);
-
-    M.print(*OS, &AW, false);
-
-    return false;
-  }
-
-  void getAnalysisUsage(AnalysisUsage &AU) const override {
-    AU.setPreservesAll();
-  }
-
-  static StringRef name() { return "RustPrintModulePass"; }
-};
-
 } // namespace
 
-namespace llvm {
-  void initializeRustPrintModulePassPass(PassRegistry&);
-}
-
-char RustPrintModulePass::ID = 0;
-INITIALIZE_PASS(RustPrintModulePass, "print-rust-module",
-                "Print rust module to stderr", false, false)
-
 extern "C" LLVMRustResult
-LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
-                    const char *Path, DemangleFn Demangle) {
-  llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
+LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
   std::string ErrorInfo;
-
   std::error_code EC;
   raw_fd_ostream OS(Path, EC, sys::fs::F_None);
   if (EC)
@@ -707,11 +672,9 @@
     return LLVMRustResult::Failure;
   }
 
+  RustAssemblyAnnotationWriter AAW(Demangle);
   formatted_raw_ostream FOS(OS);
-
-  PM->add(new RustPrintModulePass(FOS, Demangle));
-
-  PM->run(*unwrap(M));
+  unwrap(M)->print(FOS, &AAW);
 
   return LLVMRustResult::Success;
 }
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index a83ba9a..720928e 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -129,8 +129,9 @@
 }
 
 extern "C" LLVMValueRef
-LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty) {
-  return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty)));
+LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
+  StringRef NameRef(Name, NameLen);
+  return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty)));
 }
 
 extern "C" LLVMValueRef
@@ -1287,11 +1288,12 @@
 }
 
 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
-                                  const char *Name) {
+                                  const char *Name, size_t NameLen) {
   Triple TargetTriple(unwrap(M)->getTargetTriple());
   GlobalObject *GV = unwrap<GlobalObject>(V);
   if (!TargetTriple.isOSBinFormatMachO()) {
-    GV->setComdat(unwrap(M)->getOrInsertComdat(Name));
+    StringRef NameRef(Name, NameLen);
+    GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
   }
 }
 
diff --git a/src/test/codegen/bool-cmp.rs b/src/test/codegen/bool-cmp.rs
new file mode 100644
index 0000000..8769a4c
--- /dev/null
+++ b/src/test/codegen/bool-cmp.rs
@@ -0,0 +1,17 @@
+// This is a test for optimal Ord trait implementation for bool.
+// See <https://github.com/rust-lang/rust/issues/66780> for more info.
+
+// compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+
+use std::cmp::Ordering;
+
+// CHECK-LABEL: @cmp_bool
+#[no_mangle]
+pub fn cmp_bool(a: bool, b: bool) -> Ordering {
+// CHECK: zext i1
+// CHECK: zext i1
+// CHECK: sub nsw
+    a.cmp(&b)
+}
diff --git a/src/test/codegen/gdb_debug_script_load.rs b/src/test/codegen/gdb_debug_script_load.rs
index 2e8dc7b..178269f 100644
--- a/src/test/codegen/gdb_debug_script_load.rs
+++ b/src/test/codegen/gdb_debug_script_load.rs
@@ -1,6 +1,8 @@
 // ignore-tidy-linelength
 // ignore-windows
 // ignore-macos
+// ignore-wasm
+// ignore-emscripten
 
 // compile-flags: -g -C no-prepopulate-passes
 
diff --git a/src/test/codegen/set-discriminant-invalid.rs b/src/test/codegen/set-discriminant-invalid.rs
new file mode 100644
index 0000000..d9614f0
--- /dev/null
+++ b/src/test/codegen/set-discriminant-invalid.rs
@@ -0,0 +1,43 @@
+// compile-flags: -C opt-level=0
+#![crate_type = "lib"]
+
+pub enum ApiError {}
+#[allow(dead_code)]
+pub struct TokioError {
+    b: bool,
+}
+pub enum Error {
+    Api {
+        source: ApiError,
+    },
+    Ethereum,
+    Tokio {
+        source: TokioError,
+    },
+}
+struct Api;
+impl IntoError<Error> for Api
+{
+    type Source = ApiError;
+    // CHECK-LABEL: @into_error
+    // CHECK: llvm.trap()
+    // Also check the next two instructions to make sure we do not match against `trap`
+    // elsewhere in the code.
+    // CHECK-NEXT: load
+    // CHECK-NEXT: ret
+    #[no_mangle]
+    fn into_error(self, error: Self::Source) -> Error {
+        Error::Api {
+            source: (|v| v)(error),
+        }
+    }
+}
+
+pub trait IntoError<E>
+{
+    /// The underlying error
+    type Source;
+
+    /// Combine the information to produce the error
+    fn into_error(self, source: Self::Source) -> E;
+}
diff --git a/src/test/compile-fail/consts/const-err3.rs b/src/test/compile-fail/consts/const-err3.rs
index add4eef..fc10824 100644
--- a/src/test/compile-fail/consts/const-err3.rs
+++ b/src/test/compile-fail/consts/const-err3.rs
@@ -14,7 +14,6 @@
     //~^ ERROR const_err
     let _e = [5u8][1];
     //~^ ERROR const_err
-    //~| ERROR this expression will panic at runtime
     black_box(b);
     black_box(c);
     black_box(d);
diff --git a/src/test/compile-fail/consts/const-fn-error.rs b/src/test/compile-fail/consts/const-fn-error.rs
index 1a4fc72..5d26059 100644
--- a/src/test/compile-fail/consts/const-fn-error.rs
+++ b/src/test/compile-fail/consts/const-fn-error.rs
@@ -6,7 +6,7 @@
     let mut sum = 0;
     for i in 0..x {
         //~^ ERROR E0015
-        //~| ERROR E0017
+        //~| ERROR E0658
         //~| ERROR E0080
         //~| ERROR E0744
         //~| ERROR E0019
diff --git a/src/test/incremental/issue-61323.rs b/src/test/incremental/issue-61323.rs
new file mode 100644
index 0000000..448ce36
--- /dev/null
+++ b/src/test/incremental/issue-61323.rs
@@ -0,0 +1,15 @@
+// revisions: rpass cfail
+
+enum A {
+    //[cfail]~^ ERROR 3:1: 3:7: recursive type `A` has infinite size [E0072]
+    B(C),
+}
+
+#[cfg(rpass)]
+struct C(Box<A>);
+
+#[cfg(cfail)]
+struct C(A);
+//[cfail]~^ ERROR 12:1: 12:13: recursive type `C` has infinite size [E0072]
+
+fn main() {}
diff --git a/src/test/mir-opt/const_prop/issue-66971.rs b/src/test/mir-opt/const_prop/issue-66971.rs
new file mode 100644
index 0000000..30c7530
--- /dev/null
+++ b/src/test/mir-opt/const_prop/issue-66971.rs
@@ -0,0 +1,38 @@
+// compile-flags: -Z mir-opt-level=2
+
+// Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected
+// outputs below, after ConstProp this is how _2 would look like with the bug:
+//
+//     _2 = (const Scalar(0x00) : (), const 0u8);
+//
+// Which has the wrong type.
+
+fn encode(this: ((), u8, u8)) {
+    assert!(this.2 == 0);
+}
+
+fn main() {
+    encode(((), 0, 0));
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _3 = ();
+//      _2 = (move _3, const 0u8, const 0u8);
+//      ...
+//      _1 = const encode(move _2) -> bb1;
+//      ...
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      _3 = const Scalar(<ZST>) : ();
+//      _2 = (move _3, const 0u8, const 0u8);
+//      ...
+//      _1 = const encode(move _2) -> bb1;
+//      ...
+//  }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/issue-67019.rs b/src/test/mir-opt/const_prop/issue-67019.rs
new file mode 100644
index 0000000..c6d753a
--- /dev/null
+++ b/src/test/mir-opt/const_prop/issue-67019.rs
@@ -0,0 +1,34 @@
+// compile-flags: -Z mir-opt-level=2
+
+// This used to ICE in const-prop
+
+fn test(this: ((u8, u8),)) {
+    assert!((this.0).0 == 1);
+}
+
+fn main() {
+    test(((1, 2),));
+}
+
+// Important bit is parameter passing so we only check that below
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _3 = (const 1u8, const 2u8);
+//      _2 = (move _3,);
+//      ...
+//      _1 = const test(move _2) -> bb1;
+//      ...
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      _3 = (const 1u8, const 2u8);
+//      _2 = (move _3,);
+//      ...
+//      _1 = const test(move _2) -> bb1;
+//      ...
+//  }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/return_place.rs b/src/test/mir-opt/const_prop/return_place.rs
index cc9951b..ea7c1e7 100644
--- a/src/test/mir-opt/const_prop/return_place.rs
+++ b/src/test/mir-opt/const_prop/return_place.rs
@@ -21,9 +21,6 @@
 //         _0 = move (_1.0: u32);
 //         return;
 //     }
-//     bb2 (cleanup): {
-//         resume;
-//     }
 // }
 // END rustc.add.ConstProp.before.mir
 // START rustc.add.ConstProp.after.mir
@@ -38,9 +35,6 @@
 //         _0 = const 4u32;
 //         return;
 //     }
-//     bb2 (cleanup): {
-//         resume;
-//     }
 // }
 // END rustc.add.ConstProp.after.mir
 // START rustc.add.PreCodegen.before.mir
diff --git a/src/test/mir-opt/retain-never-const.rs b/src/test/mir-opt/retain-never-const.rs
new file mode 100644
index 0000000..5d59b2f
--- /dev/null
+++ b/src/test/mir-opt/retain-never-const.rs
@@ -0,0 +1,28 @@
+// Regression test for #66975 - ensure that we don't keep unevaluated
+// `!`-typed constants until codegen.
+
+// Force generation of optimized mir for functions that do not reach codegen.
+// compile-flags: --emit mir,link
+
+#![feature(const_panic)]
+
+struct PrintName<T>(T);
+
+impl<T> PrintName<T> {
+    const VOID: ! = panic!();
+}
+
+fn no_codegen<T>() {
+    let _ = PrintName::<T>::VOID;
+}
+
+fn main() {}
+
+// END RUST SOURCE
+// START rustc.no_codegen.PreCodegen.after.mir
+// bb0: {
+//     StorageLive(_1);
+//     _1 = const PrintName::<T>::VOID;
+//     unreachable;
+// }
+// END rustc.no_codegen.PreCodegen.after.mir
diff --git a/src/test/mir-opt/uniform_array_move_out.rs b/src/test/mir-opt/uniform_array_move_out.rs
index c249154..f2e1864 100644
--- a/src/test/mir-opt/uniform_array_move_out.rs
+++ b/src/test/mir-opt/uniform_array_move_out.rs
@@ -18,58 +18,12 @@
 
 // END RUST SOURCE
 
-// START rustc.move_out_from_end.UniformArrayMoveOut.before.mir
-//     StorageLive(_6);
-//      _6 = move _1[-1 of 1];
-//      _0 = ();
-// END rustc.move_out_from_end.UniformArrayMoveOut.before.mir
-
-// START rustc.move_out_from_end.UniformArrayMoveOut.after.mir
-//     StorageLive(_6);
+// START rustc.move_out_from_end.mir_map.0.mir
 //      _6 = move _1[1 of 2];
-//      nop;
 //      _0 = ();
-// END rustc.move_out_from_end.UniformArrayMoveOut.after.mir
+// END rustc.move_out_from_end.mir_map.0.mir
 
-// START rustc.move_out_by_subslice.UniformArrayMoveOut.before.mir
-//     StorageLive(_6);
-//      _6 = move _1[0:];
-// END rustc.move_out_by_subslice.UniformArrayMoveOut.before.mir
-
-// START rustc.move_out_by_subslice.UniformArrayMoveOut.after.mir
-//     StorageLive(_6);
-//     StorageLive(_7);
-//     _7 = move _1[0 of 2];
-//     StorageLive(_8);
-//     _8 = move _1[1 of 2];
-//     _6 = [move _7, move _8];
-//     StorageDead(_7);
-//     StorageDead(_8);
-//     nop;
+// START rustc.move_out_by_subslice.mir_map.0.mir
+//     _6 = move _1[0..2];
 //     _0 = ();
-// END rustc.move_out_by_subslice.UniformArrayMoveOut.after.mir
-
-// START rustc.move_out_by_subslice.RestoreSubsliceArrayMoveOut.before.mir
-//     StorageLive(_6);
-//     StorageLive(_7);
-//     _7 = move _1[0 of 2];
-//     StorageLive(_8);
-//     _8 = move _1[1 of 2];
-//     _6 = [move _7, move _8];
-//     StorageDead(_7);
-//     StorageDead(_8);
-//     _0 = ();
-// END rustc.move_out_by_subslice.RestoreSubsliceArrayMoveOut.before.mir
-
-// START rustc.move_out_by_subslice.RestoreSubsliceArrayMoveOut.after.mir
-//     StorageLive(_6);
-//     nop;
-//     nop;
-//     nop;
-//     nop;
-//     _6 = move _1[0:];
-//     nop;
-//     nop;
-//     nop;
-//     _0 = ();
-// END rustc.move_out_by_subslice.RestoreSubsliceArrayMoveOut.after.mir
+// END rustc.move_out_by_subslice.mir_map.0.mir
diff --git a/src/test/pretty/enum-variant-vis.rs b/src/test/pretty/enum-variant-vis.rs
new file mode 100644
index 0000000..a3e8178
--- /dev/null
+++ b/src/test/pretty/enum-variant-vis.rs
@@ -0,0 +1,8 @@
+// pp-exact
+
+// Check that the visibility is printed on an enum variant.
+
+fn main() { }
+
+#[cfg(FALSE)]
+enum Foo { pub V, }
diff --git a/src/test/rustdoc-ui/issue-61732.rs b/src/test/rustdoc-ui/issue-61732.rs
new file mode 100644
index 0000000..d4835c0
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61732.rs
@@ -0,0 +1,4 @@
+// This previously triggered an ICE.
+
+pub(in crate::r#mod) fn main() {}
+//~^ ERROR expected module, found unresolved item
diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr
new file mode 100644
index 0000000..6c8ba48
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-61732.stderr
@@ -0,0 +1,11 @@
+error[E0577]: expected module, found unresolved item `crate::r#mod`
+  --> $DIR/issue-61732.rs:3:8
+   |
+LL | pub(in crate::r#mod) fn main() {}
+   |        ^^^^^^^^^^^^ not a module
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0577`.
diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs
new file mode 100644
index 0000000..505d6ee
--- /dev/null
+++ b/src/test/rustdoc/duplicate-cfg.rs
@@ -0,0 +1,15 @@
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+
+// @has 'foo/index.html'
+// @!has '-' '//*[@class="stab portability"]' 'feature="sync" and'
+// @has '-' '//*[@class="stab portability"]' 'feature="sync"'
+#[doc(cfg(feature = "sync"))]
+#[doc(cfg(feature = "sync"))]
+pub struct Foo;
+
+#[doc(cfg(feature = "sync"))]
+pub mod bar {
+    #[doc(cfg(feature = "sync"))]
+    pub struct Bar;
+}
diff --git a/src/test/rustdoc/issue-66159.rs b/src/test/rustdoc/issue-66159.rs
index a69ba61..003d079a 100644
--- a/src/test/rustdoc/issue-66159.rs
+++ b/src/test/rustdoc/issue-66159.rs
@@ -1,6 +1,5 @@
-// aux-build:issue-66159-1.rs
+// aux-crate:priv:issue_66159_1=issue-66159-1.rs
 // compile-flags:-Z unstable-options
-// extern-private:issue_66159_1
 
 // The issue was an ICE which meant that we never actually generated the docs
 // so if we have generated the docs, we're okay.
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
index 9be44c7..c6d9a61 100644
--- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
@@ -121,3 +121,4 @@
 
 error: aborting due to 11 previous errors
 
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/associated-const/issue-63496.rs b/src/test/ui/associated-const/issue-63496.rs
index 311c48b..f9f663a 100644
--- a/src/test/ui/associated-const/issue-63496.rs
+++ b/src/test/ui/associated-const/issue-63496.rs
@@ -2,8 +2,8 @@
     const C: usize;
 
     fn f() -> ([u8; A::C], [u8; A::C]);
-    //~^ ERROR: type annotations needed: cannot resolve
-    //~| ERROR: type annotations needed: cannot resolve
+    //~^ ERROR: type annotations needed
+    //~| ERROR: type annotations needed
 }
 
 fn main() {}
diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr
index 70bb12d..23916a3 100644
--- a/src/test/ui/associated-const/issue-63496.stderr
+++ b/src/test/ui/associated-const/issue-63496.stderr
@@ -1,20 +1,24 @@
-error[E0283]: type annotations needed: cannot resolve `_: A`
+error[E0283]: type annotations needed
   --> $DIR/issue-63496.rs:4:21
    |
 LL |     const C: usize;
    |     --------------- required by `A::C`
 LL | 
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                     ^^^^
+   |                     ^^^^ cannot infer type
+   |
+   = note: cannot resolve `_: A`
 
-error[E0283]: type annotations needed: cannot resolve `_: A`
+error[E0283]: type annotations needed
   --> $DIR/issue-63496.rs:4:33
    |
 LL |     const C: usize;
    |     --------------- required by `A::C`
 LL | 
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                                 ^^^^
+   |                                 ^^^^ cannot infer type
+   |
+   = note: cannot resolve `_: A`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr
index 562146a..9c825d5 100644
--- a/src/test/ui/associated-item/issue-48027.stderr
+++ b/src/test/ui/associated-item/issue-48027.stderr
@@ -7,13 +7,15 @@
 LL | impl dyn Bar {}
    |      ^^^^^^^ the trait `Bar` cannot be made into an object
 
-error[E0283]: type annotations needed: cannot resolve `_: Bar`
+error[E0283]: type annotations needed
   --> $DIR/issue-48027.rs:3:32
    |
 LL |     const X: usize;
    |     --------------- required by `Bar::X`
 LL |     fn return_n(&self) -> [u8; Bar::X];
-   |                                ^^^^^^
+   |                                ^^^^^^ cannot infer type
+   |
+   = note: cannot resolve `_: Bar`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr
index 5ef1b23..069da95 100644
--- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr
+++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr
@@ -1,18 +1,23 @@
-error[E0284]: type annotations needed: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
+error[E0284]: type annotations needed
   --> $DIR/associated-types-overridden-binding.rs:4:1
    |
 LL | trait Foo: Iterator<Item = i32> {}
    | ------------------------------- required by `Foo`
 LL | trait Bar: Foo<Item = u32> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Self`
+   |
+   = note: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
 
-error[E0282]: type annotations needed
+error[E0284]: type annotations needed
   --> $DIR/associated-types-overridden-binding.rs:7:1
    |
+LL | trait I32Iterator = Iterator<Item = i32>;
+   | ----------------------------------------- required by `I32Iterator`
 LL | trait U32Iterator = I32Iterator<Item = u32>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Self`
+   |
+   = note: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0282, E0284.
-For more information about an error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr
index 4e9e54d..14ce483 100644
--- a/src/test/ui/associated-types/associated-types-unconstrained.stderr
+++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr
@@ -1,8 +1,10 @@
-error[E0284]: type annotations needed: cannot resolve `<_ as Foo>::A == _`
+error[E0284]: type annotations needed
   --> $DIR/associated-types-unconstrained.rs:14:20
    |
 LL |     let x: isize = Foo::bar();
-   |                    ^^^^^^^^
+   |                    ^^^^^^^^ cannot infer type
+   |
+   = note: cannot resolve `<_ as Foo>::A == _`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
index 627609c..3e39c8a 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
@@ -9,13 +9,21 @@
    |
 LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
    |        ^^
-   = note: ...so that the expression is assignable:
-           expected Type<'_>
-              found Type<'a>
+note: ...so that the expression is assignable
+  --> $DIR/project-fn-ret-invariant.rs:48:13
+   |
+LL |    bar(foo, x)
+   |             ^
+   = note: expected  `Type<'_>`
+              found  `Type<'a>`
    = note: but, the lifetime must be valid for the static lifetime...
-   = note: ...so that the expression is assignable:
-           expected Type<'static>
-              found Type<'_>
+note: ...so that the expression is assignable
+  --> $DIR/project-fn-ret-invariant.rs:48:4
+   |
+LL |    bar(foo, x)
+   |    ^^^^^^^^^^^
+   = note: expected  `Type<'static>`
+              found  `Type<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/async-fn-nonsend.rs b/src/test/ui/async-await/async-fn-nonsend.rs
index 1f1bf42..645c903 100644
--- a/src/test/ui/async-await/async-fn-nonsend.rs
+++ b/src/test/ui/async-await/async-fn-nonsend.rs
@@ -48,10 +48,10 @@
 
 pub fn pass_assert() {
     assert_send(local_dropped_before_await());
-    //~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
+    //~^ ERROR future cannot be sent between threads safely
     assert_send(non_send_temporary_in_match());
-    //~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
+    //~^ ERROR future cannot be sent between threads safely
     assert_send(non_sync_with_method_call());
-    //~^ ERROR `dyn std::fmt::Write` cannot be sent between threads safely
-    //~^^ ERROR `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
+    //~^ ERROR future cannot be sent between threads safely
+    //~^^ ERROR future cannot be sent between threads safely
 }
diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr
index 6e89deb..5c870ca 100644
--- a/src/test/ui/async-await/async-fn-nonsend.stderr
+++ b/src/test/ui/async-await/async-fn-nonsend.stderr
@@ -1,79 +1,88 @@
-error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
+error: future cannot be sent between threads safely
   --> $DIR/async-fn-nonsend.rs:50:5
    |
 LL | fn assert_send(_: impl Send) {}
    |    -----------         ---- required by this bound in `assert_send`
 ...
 LL |     assert_send(local_dropped_before_await());
-   |     ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
+   |     ^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send`
    |
    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
-   = note: required because it appears within the type `impl std::fmt::Debug`
-   = note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}`
-   = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}]`
-   = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, impl std::future::Future, ()}]>`
-   = note: required because it appears within the type `impl std::future::Future`
-   = note: required because it appears within the type `impl std::future::Future`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/async-fn-nonsend.rs:25:5
+   |
+LL |     let x = non_send();
+   |         - has type `impl std::fmt::Debug`
+LL |     drop(x);
+LL |     fut().await;
+   |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+   | - `x` is later dropped here
 
-error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
+error: future cannot be sent between threads safely
   --> $DIR/async-fn-nonsend.rs:52:5
    |
 LL | fn assert_send(_: impl Send) {}
    |    -----------         ---- required by this bound in `assert_send`
 ...
 LL |     assert_send(non_send_temporary_in_match());
-   |     ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
+   |     ^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
    |
    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
-   = note: required because it appears within the type `impl std::fmt::Debug`
-   = note: required because it appears within the type `{impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, impl std::future::Future, ()}`
-   = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, impl std::future::Future, ()}]`
-   = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, impl std::future::Future, ()}]>`
-   = note: required because it appears within the type `impl std::future::Future`
-   = note: required because it appears within the type `impl std::future::Future`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/async-fn-nonsend.rs:34:20
+   |
+LL |     match Some(non_send()) {
+   |                ---------- has type `impl std::fmt::Debug`
+LL |         Some(_) => fut().await,
+   |                    ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later
+...
+LL | }
+   | - `non_send()` is later dropped here
 
-error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely
+error: future cannot be sent between threads safely
   --> $DIR/async-fn-nonsend.rs:54:5
    |
 LL | fn assert_send(_: impl Send) {}
    |    -----------         ---- required by this bound in `assert_send`
 ...
 LL |     assert_send(non_sync_with_method_call());
-   |     ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely
+   |     ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
    |
    = help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write`
-   = note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write`
-   = note: required because it appears within the type `std::fmt::Formatter<'_>`
-   = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>`
-   = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}`
-   = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]`
-   = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]>`
-   = note: required because it appears within the type `impl std::future::Future`
-   = note: required because it appears within the type `impl std::future::Future`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/async-fn-nonsend.rs:43:9
+   |
+LL |     let f: &mut std::fmt::Formatter = panic!();
+   |         - has type `&mut std::fmt::Formatter<'_>`
+LL |     if non_sync().fmt(f).unwrap() == () {
+LL |         fut().await;
+   |         ^^^^^^^^^^^ await occurs here, with `f` maybe used later
+LL |     }
+LL | }
+   | - `f` is later dropped here
 
-error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
+error: future cannot be sent between threads safely
   --> $DIR/async-fn-nonsend.rs:54:5
    |
 LL | fn assert_send(_: impl Send) {}
    |    -----------         ---- required by this bound in `assert_send`
 ...
 LL |     assert_send(non_sync_with_method_call());
-   |     ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
+   |     ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
    |
    = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
-   = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
-   = note: required because it appears within the type `core::fmt::Void`
-   = note: required because it appears within the type `&core::fmt::Void`
-   = note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
-   = note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>`
-   = note: required because it appears within the type `std::fmt::Formatter<'_>`
-   = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>`
-   = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}`
-   = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]`
-   = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, bool, impl std::future::Future, impl std::future::Future, ()}]>`
-   = note: required because it appears within the type `impl std::future::Future`
-   = note: required because it appears within the type `impl std::future::Future`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/async-fn-nonsend.rs:43:9
+   |
+LL |     let f: &mut std::fmt::Formatter = panic!();
+   |         - has type `&mut std::fmt::Formatter<'_>`
+LL |     if non_sync().fmt(f).unwrap() == () {
+LL |         fut().await;
+   |         ^^^^^^^^^^^ await occurs here, with `f` maybe used later
+LL |     }
+LL | }
+   | - `f` is later dropped here
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/issue-64130-1-sync.rs b/src/test/ui/async-await/issue-64130-1-sync.rs
new file mode 100644
index 0000000..cc5ca89
--- /dev/null
+++ b/src/test/ui/async-await/issue-64130-1-sync.rs
@@ -0,0 +1,23 @@
+#![feature(optin_builtin_traits)]
+// edition:2018
+
+// This tests the the specialized async-await-specific error when futures don't implement an
+// auto trait (which is specifically Sync) due to some type that was captured.
+
+struct Foo;
+
+impl !Sync for Foo {}
+
+fn is_sync<T: Sync>(t: T) { }
+
+async fn bar() {
+    let x = Foo;
+    baz().await;
+}
+
+async fn baz() { }
+
+fn main() {
+    is_sync(bar());
+    //~^ ERROR future cannot be shared between threads safely
+}
diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr
new file mode 100644
index 0000000..8beb31f
--- /dev/null
+++ b/src/test/ui/async-await/issue-64130-1-sync.stderr
@@ -0,0 +1,22 @@
+error: future cannot be shared between threads safely
+  --> $DIR/issue-64130-1-sync.rs:21:5
+   |
+LL | fn is_sync<T: Sync>(t: T) { }
+   |    -------    ---- required by this bound in `is_sync`
+...
+LL |     is_sync(bar());
+   |     ^^^^^^^ future returned by `bar` is not `Sync`
+   |
+   = help: within `impl std::future::Future`, the trait `std::marker::Sync` is not implemented for `Foo`
+note: future is not `Sync` as this value is used across an await
+  --> $DIR/issue-64130-1-sync.rs:15:5
+   |
+LL |     let x = Foo;
+   |         - has type `Foo`
+LL |     baz().await;
+   |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+   | - `x` is later dropped here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/issue-64130-2-send.rs b/src/test/ui/async-await/issue-64130-2-send.rs
new file mode 100644
index 0000000..1efe2ab
--- /dev/null
+++ b/src/test/ui/async-await/issue-64130-2-send.rs
@@ -0,0 +1,23 @@
+#![feature(optin_builtin_traits)]
+// edition:2018
+
+// This tests the the specialized async-await-specific error when futures don't implement an
+// auto trait (which is specifically Send) due to some type that was captured.
+
+struct Foo;
+
+impl !Send for Foo {}
+
+fn is_send<T: Send>(t: T) { }
+
+async fn bar() {
+    let x = Foo;
+    baz().await;
+}
+
+async fn baz() { }
+
+fn main() {
+    is_send(bar());
+    //~^ ERROR future cannot be sent between threads safely
+}
diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr
new file mode 100644
index 0000000..823b88e
--- /dev/null
+++ b/src/test/ui/async-await/issue-64130-2-send.stderr
@@ -0,0 +1,22 @@
+error: future cannot be sent between threads safely
+  --> $DIR/issue-64130-2-send.rs:21:5
+   |
+LL | fn is_send<T: Send>(t: T) { }
+   |    -------    ---- required by this bound in `is_send`
+...
+LL |     is_send(bar());
+   |     ^^^^^^^ future returned by `bar` is not `Send`
+   |
+   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `Foo`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/issue-64130-2-send.rs:15:5
+   |
+LL |     let x = Foo;
+   |         - has type `Foo`
+LL |     baz().await;
+   |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+   | - `x` is later dropped here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/issue-64130-3-other.rs b/src/test/ui/async-await/issue-64130-3-other.rs
new file mode 100644
index 0000000..901544e
--- /dev/null
+++ b/src/test/ui/async-await/issue-64130-3-other.rs
@@ -0,0 +1,25 @@
+#![feature(optin_builtin_traits)]
+// edition:2018
+
+// This tests the the unspecialized async-await-specific error when futures don't implement an
+// auto trait (which is not Send or Sync) due to some type that was captured.
+
+auto trait Qux { }
+
+struct Foo;
+
+impl !Qux for Foo {}
+
+fn is_qux<T: Qux>(t: T) { }
+
+async fn bar() {
+    let x = Foo;
+    baz().await;
+}
+
+async fn baz() { }
+
+fn main() {
+    is_qux(bar());
+    //~^ ERROR the trait bound `Foo: Qux` is not satisfied in `impl std::future::Future`
+}
diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr
new file mode 100644
index 0000000..155c5cc
--- /dev/null
+++ b/src/test/ui/async-await/issue-64130-3-other.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl std::future::Future`
+  --> $DIR/issue-64130-3-other.rs:23:5
+   |
+LL | fn is_qux<T: Qux>(t: T) { }
+   |    ------    --- required by this bound in `is_qux`
+...
+LL |     is_qux(bar());
+   |     ^^^^^^ within `impl std::future::Future`, the trait `Qux` is not implemented for `Foo`
+   |
+   = help: the following implementations were found:
+             <Foo as Qux>
+note: future does not implement `Qux` as this value is used across an await
+  --> $DIR/issue-64130-3-other.rs:17:5
+   |
+LL |     let x = Foo;
+   |         - has type `Foo`
+LL |     baz().await;
+   |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+   | - `x` is later dropped here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/issue-64130-4-async-move.rs b/src/test/ui/async-await/issue-64130-4-async-move.rs
new file mode 100644
index 0000000..2538f34
--- /dev/null
+++ b/src/test/ui/async-await/issue-64130-4-async-move.rs
@@ -0,0 +1,28 @@
+// edition:2018
+use std::any::Any;
+use std::future::Future;
+
+struct Client(Box<dyn Any + Send>);
+
+impl Client {
+    fn status(&self) -> u16 {
+        200
+    }
+}
+
+async fn get() { }
+
+pub fn foo() -> impl Future + Send {
+    //~^ ERROR future cannot be sent between threads safely
+    let client = Client(Box::new(true));
+    async move {
+        match client.status() {
+            200 => {
+                let _x = get().await;
+            },
+            _ => (),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr
new file mode 100644
index 0000000..ddbb469
--- /dev/null
+++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr
@@ -0,0 +1,22 @@
+error: future cannot be sent between threads safely
+  --> $DIR/issue-64130-4-async-move.rs:15:17
+   |
+LL | pub fn foo() -> impl Future + Send {
+   |                 ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/issue-64130-4-async-move.rs:21:26
+   |
+LL |         match client.status() {
+   |               ------ has type `&Client`
+LL |             200 => {
+LL |                 let _x = get().await;
+   |                          ^^^^^^^^^^^ await occurs here, with `client` maybe used later
+...
+LL |     }
+   |     - `client` is later dropped here
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.rs b/src/test/ui/async-await/issue-64130-non-send-future-diags.rs
index 1936d1a..656ade6 100644
--- a/src/test/ui/async-await/issue-64130-non-send-future-diags.rs
+++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.rs
@@ -1,10 +1,10 @@
 // edition:2018
 
+// This tests the basic example case for the async-await-specific error.
+
 use std::sync::Mutex;
 
-fn is_send<T: Send>(t: T) {
-
-}
+fn is_send<T: Send>(t: T) { }
 
 async fn foo() {
     bar(&Mutex::new(22)).await;
@@ -15,11 +15,9 @@
     baz().await;
 }
 
-async fn baz() {
-
-}
+async fn baz() { }
 
 fn main() {
     is_send(foo());
-    //~^ ERROR `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely [E0277]
+    //~^ ERROR future cannot be sent between threads safely
 }
diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr
index 9e9fc52..662407f 100644
--- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr
+++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr
@@ -1,14 +1,14 @@
-error[E0277]: `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely
-  --> $DIR/issue-64130-non-send-future-diags.rs:23:5
+error: future cannot be sent between threads safely
+  --> $DIR/issue-64130-non-send-future-diags.rs:21:5
    |
-LL | fn is_send<T: Send>(t: T) {
+LL | fn is_send<T: Send>(t: T) { }
    |    -------    ---- required by this bound in `is_send`
 ...
 LL |     is_send(foo());
-   |     ^^^^^^^ `std::sync::MutexGuard<'_, u32>` cannot be sent between threads safely
+   |     ^^^^^^^ future returned by `foo` is not `Send`
    |
    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, u32>`
-note: future does not implement `std::marker::Send` as this value is used across an await
+note: future is not `Send` as this value is used across an await
   --> $DIR/issue-64130-non-send-future-diags.rs:15:5
    |
 LL |     let g = x.lock().unwrap();
@@ -20,4 +20,3 @@
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs b/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs
new file mode 100644
index 0000000..c8c2702
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs
@@ -0,0 +1,15 @@
+// edition:2018
+
+struct Ia<S>(S);
+
+impl<S> Ia<S> {
+    fn partial(_: S) {}
+    fn full(self) {}
+
+    async fn crash(self) {
+        Self::partial(self.0);
+        Self::full(self); //~ ERROR use of moved value: `self`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr b/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr
new file mode 100644
index 0000000..9177b83
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `self`
+  --> $DIR/issue-66958-non-copy-infered-type-arg.rs:11:20
+   |
+LL |         Self::partial(self.0);
+   |                       ------ value moved here
+LL |         Self::full(self);
+   |                    ^^^^ value used here after partial move
+   |
+   = note: move occurs because `self.0` has type `S`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/async-await/suggest-missing-await.fixed b/src/test/ui/async-await/suggest-missing-await.fixed
index 7c02a90..1ec59d9 100644
--- a/src/test/ui/async-await/suggest-missing-await.fixed
+++ b/src/test/ui/async-await/suggest-missing-await.fixed
@@ -16,4 +16,15 @@
     //~| SUGGESTION x.await
 }
 
+async fn dummy() {}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn_return() {
+    dummy().await;
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP try adding a semicolon
+    //~| HELP consider using `.await` here
+    //~| SUGGESTION dummy().await
+}
+
 fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs
index 91abd44..70cc1f1 100644
--- a/src/test/ui/async-await/suggest-missing-await.rs
+++ b/src/test/ui/async-await/suggest-missing-await.rs
@@ -16,4 +16,15 @@
     //~| SUGGESTION x.await
 }
 
+async fn dummy() {}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn_return() {
+    dummy()
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP try adding a semicolon
+    //~| HELP consider using `.await` here
+    //~| SUGGESTION dummy().await
+}
+
 fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr
index 7a635a3..7ab0244 100644
--- a/src/test/ui/async-await/suggest-missing-await.stderr
+++ b/src/test/ui/async-await/suggest-missing-await.stderr
@@ -10,6 +10,23 @@
    = note:     expected type `u32`
            found opaque type `impl std::future::Future`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/suggest-missing-await.rs:23:5
+   |
+LL |     dummy()
+   |     ^^^^^^^ expected `()`, found opaque type
+   |
+   = note: expected unit type `()`
+            found opaque type `impl std::future::Future`
+help: try adding a semicolon
+   |
+LL |     dummy();
+   |            ^
+help: consider using `.await` here
+   |
+LL |     dummy().await
+   |
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/async-await/unresolved_type_param.rs b/src/test/ui/async-await/unresolved_type_param.rs
index 2876f9f..79c043b 100644
--- a/src/test/ui/async-await/unresolved_type_param.rs
+++ b/src/test/ui/async-await/unresolved_type_param.rs
@@ -8,7 +8,7 @@
 async fn foo() {
     bar().await;
     //~^ ERROR type inside `async fn` body must be known in this context
-    //~| NOTE cannot infer type for `T`
+    //~| NOTE cannot infer type for type parameter `T`
     //~| NOTE the type is part of the `async fn` body because of this `await`
     //~| NOTE in this expansion of desugaring of `await`
 }
diff --git a/src/test/ui/async-await/unresolved_type_param.stderr b/src/test/ui/async-await/unresolved_type_param.stderr
index c7866fc..b9b4f51 100644
--- a/src/test/ui/async-await/unresolved_type_param.stderr
+++ b/src/test/ui/async-await/unresolved_type_param.stderr
@@ -2,7 +2,7 @@
   --> $DIR/unresolved_type_param.rs:9:5
    |
 LL |     bar().await;
-   |     ^^^ cannot infer type for `T`
+   |     ^^^ cannot infer type for type parameter `T`
    |
 note: the type is part of the `async fn` body because of this `await`
   --> $DIR/unresolved_type_param.rs:9:5
diff --git a/src/test/ui/attributes/field-attributes-vis-unresolved.rs b/src/test/ui/attributes/field-attributes-vis-unresolved.rs
new file mode 100644
index 0000000..d1bd2a1
--- /dev/null
+++ b/src/test/ui/attributes/field-attributes-vis-unresolved.rs
@@ -0,0 +1,25 @@
+// Non-builtin attributes do not mess with field visibility resolution (issue #67006).
+
+mod internal {
+    struct S {
+        #[rustfmt::skip]
+        pub(in crate::internal) field: u8 // OK
+    }
+
+    struct Z(
+        #[rustfmt::skip]
+        pub(in crate::internal) u8 // OK
+    );
+}
+
+struct S {
+    #[rustfmt::skip]
+    pub(in nonexistent) field: u8 //~ ERROR failed to resolve
+}
+
+struct Z(
+    #[rustfmt::skip]
+    pub(in nonexistent) u8 //~ ERROR failed to resolve
+);
+
+fn main() {}
diff --git a/src/test/ui/attributes/field-attributes-vis-unresolved.stderr b/src/test/ui/attributes/field-attributes-vis-unresolved.stderr
new file mode 100644
index 0000000..41c3cea
--- /dev/null
+++ b/src/test/ui/attributes/field-attributes-vis-unresolved.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
+  --> $DIR/field-attributes-vis-unresolved.rs:17:12
+   |
+LL |     pub(in nonexistent) field: u8
+   |            ^^^^^^^^^^^ maybe a missing crate `nonexistent`?
+
+error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
+  --> $DIR/field-attributes-vis-unresolved.rs:22:12
+   |
+LL |     pub(in nonexistent) u8
+   |            ^^^^^^^^^^^ maybe a missing crate `nonexistent`?
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs
new file mode 100644
index 0000000..8f274cf
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs
@@ -0,0 +1,69 @@
+// check-pass
+
+#![feature(slice_patterns)]
+
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_one_from_end() {
+    let a = array();
+    let [_, _, _x] = a;
+    let [.., _y, _] = a;
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    let [_, _, (_x, _)] = a;
+    let [.., (_, _y)] = a;
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    let [_x, _, _] = a;
+    let [_, _y @ ..] = a;
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    let [.., _x] = a;
+    let [_y @ .., _] = a;
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    let [(_x, _), _, _] = a;
+    let [_, _y @ ..] = a;
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    let [.., (_x, _)] = a;
+    let [_y @ .., _] = a;
+}
+
+fn move_out_by_const_subslice_and_index_field() {
+    let a = array();
+    let [_, _y @ ..] = a;
+    let [(_x, _), _, _] = a;
+}
+
+fn move_out_by_const_subslice_and_end_index_field() {
+    let a = array();
+    let [_y @ .., _] = a;
+    let [.., (_x, _)] = a;
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    let [x @ .., _, _] = a;
+    let [_, _y @ ..] = a;
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs
new file mode 100644
index 0000000..57ce241
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs
@@ -0,0 +1,69 @@
+// check-pass
+
+#![feature(slice_patterns)]
+
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_one_from_end() {
+    let a = array();
+    let [_, _, _x] = a;
+    let [.., ref _y, _] = a;
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    let [_, _, (_x, _)] = a;
+    let [.., (_, ref _y)] = a;
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    let [_x, _, _] = a;
+    let [_, ref _y @ ..] = a;
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    let [.., _x] = a;
+    let [ref _y @ .., _] = a;
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    let [(_x, _), _, _] = a;
+    let [_, ref _y @ ..] = a;
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    let [.., (_x, _)] = a;
+    let [ref _y @ .., _] = a;
+}
+
+fn move_out_by_const_subslice_and_index_field() {
+    let a = array();
+    let [_, _y @ ..] = a;
+    let [(ref _x, _), _, _] = a;
+}
+
+fn move_out_by_const_subslice_and_end_index_field() {
+    let a = array();
+    let [_y @ .., _] = a;
+    let [.., (ref _x, _)] = a;
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    let [x @ .., _, _] = a;
+    let [_, ref _y @ ..] = a;
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs
new file mode 100644
index 0000000..778beef
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs
@@ -0,0 +1,99 @@
+#![feature(slice_patterns)]
+
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
+fn move_out_from_begin_and_end() {
+    let a = array();
+    let [_, _, _x] = a;
+    let [.., ref _y] = a; //~ ERROR [E0382]
+}
+
+fn move_out_from_begin_field_and_end() {
+    let a = array();
+    let [_, _, (_x, _)] = a;
+    let [.., ref _y] = a; //~ ERROR [E0382]
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    let [_, _, (_x, _)] = a;
+    let [.., (ref _y, _)] = a; //~ ERROR [E0382]
+}
+
+// Const Index + Slice
+
+fn move_out_by_const_index_and_subslice() {
+    let a = array();
+    let [_x, _, _] = a;
+    let [ref _y @ .., _, _] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    let [.., _x] = a;
+    let [_, _, ref _y @ ..] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    let [(_x, _), _, _] = a;
+    let [ref _y @ .., _, _] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    let [.., (_x, _)] = a;
+    let [_, _, ref _y @ ..] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_subslice_and_const_index_field() {
+    let a = array();
+    let [_y @ .., _, _] = a;
+    let [(ref _x, _), _, _] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_subslice_and_const_index_end_field() {
+    let a = array();
+    let [_, _, _y @ ..] = a;
+    let [.., (ref _x, _)] = a; //~ ERROR [E0382]
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    let [x @ .., _] = a;
+    let [_, ref _y @ ..] = a; //~ ERROR [E0382]
+}
+
+// Move + Assign
+
+fn move_out_and_assign_end() {
+    let mut a = array();
+    let [_, _, _x] = a;
+    a[2] = Default::default(); //~ ERROR [E0382]
+}
+
+fn move_out_and_assign_end_field() {
+    let mut a = array();
+    let [_, _, (_x, _)] = a;
+    a[2].1 = Default::default(); //~ ERROR [E0382]
+}
+
+fn move_out_slice_and_assign_end() {
+    let mut a = array();
+    let [_, _, _x @ ..] = a;
+    a[0] = Default::default(); //~ ERROR [E0382]
+}
+
+fn move_out_slice_and_assign_end_field() {
+    let mut a = array();
+    let [_, _, _x @ ..] = a;
+    a[0].1 = Default::default(); //~ ERROR [E0382]
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
new file mode 100644
index 0000000..2a7b891
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
@@ -0,0 +1,143 @@
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use.rs:12:14
+   |
+LL |     let [_, _, _x] = a;
+   |                -- value moved here
+LL |     let [.., ref _y] = a;
+   |              ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use.rs:18:14
+   |
+LL |     let [_, _, (_x, _)] = a;
+   |                 -- value moved here
+LL |     let [.., ref _y] = a;
+   |              ^^^^^^ value borrowed here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array-use.rs:24:15
+   |
+LL |     let [_, _, (_x, _)] = a;
+   |                 -- value moved here
+LL |     let [.., (ref _y, _)] = a;
+   |               ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use.rs:32:10
+   |
+LL |     let [_x, _, _] = a;
+   |          -- value moved here
+LL |     let [ref _y @ .., _, _] = a;
+   |          ^^^^^^^^^^^ value borrowed here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use.rs:38:16
+   |
+LL |     let [.., _x] = a;
+   |              -- value moved here
+LL |     let [_, _, ref _y @ ..] = a;
+   |                ^^^^^^^^^^^ value borrowed here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use.rs:44:10
+   |
+LL |     let [(_x, _), _, _] = a;
+   |           -- value moved here
+LL |     let [ref _y @ .., _, _] = a;
+   |          ^^^^^^^^^^^ value borrowed here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use.rs:50:16
+   |
+LL |     let [.., (_x, _)] = a;
+   |               -- value moved here
+LL |     let [_, _, ref _y @ ..] = a;
+   |                ^^^^^^^^^^^ value borrowed here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use.rs:56:11
+   |
+LL |     let [_y @ .., _, _] = a;
+   |          ------- value moved here
+LL |     let [(ref _x, _), _, _] = a;
+   |           ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a[..]`
+  --> $DIR/borrowck-move-out-from-array-use.rs:62:15
+   |
+LL |     let [_, _, _y @ ..] = a;
+   |                ------- value moved here
+LL |     let [.., (ref _x, _)] = a;
+   |               ^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use.rs:70:13
+   |
+LL |     let [x @ .., _] = a;
+   |          ------ value moved here
+LL |     let [_, ref _y @ ..] = a;
+   |             ^^^^^^^^^^^ value borrowed here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use.rs:78:5
+   |
+LL |     let [_, _, _x] = a;
+   |                -- value moved here
+LL |     a[2] = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use.rs:84:5
+   |
+LL |     let [_, _, (_x, _)] = a;
+   |                 -- value moved here
+LL |     a[2].1 = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use.rs:90:5
+   |
+LL |     let [_, _, _x @ ..] = a;
+   |                ------- value moved here
+LL |     a[0] = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array-use.rs:96:5
+   |
+LL |     let [_, _, _x @ ..] = a;
+   |                ------- value moved here
+LL |     a[0].1 = Default::default();
+   |     ^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.rs b/src/test/ui/borrowck/borrowck-move-out-from-array.rs
index ee6abf4..f9d3f6f 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.rs
@@ -1,16 +1,73 @@
-#![feature(box_syntax)]
 #![feature(slice_patterns)]
 
+fn array() -> [(String, String); 3] {
+    Default::default()
+}
+
+// Const Index + Const Index
+
 fn move_out_from_begin_and_end() {
-    let a = [box 1, box 2];
-    let [_, _x] = a;
+    let a = array();
+    let [_, _, _x] = a;
     let [.., _y] = a; //~ ERROR [E0382]
 }
 
+fn move_out_from_begin_field_and_end() {
+    let a = array();
+    let [_, _, (_x, _)] = a;
+    let [.., _y] = a; //~ ERROR [E0382]
+}
+
+fn move_out_from_begin_field_and_end_field() {
+    let a = array();
+    let [_, _, (_x, _)] = a;
+    let [.., (_y, _)] = a; //~ ERROR [E0382]
+}
+
+// Const Index + Slice
+
 fn move_out_by_const_index_and_subslice() {
-    let a = [box 1, box 2];
-    let [_x, _] = a;
-    let [_y @ ..] = a; //~ ERROR [E0382]
+    let a = array();
+    let [_x, _, _] = a;
+    let [_y @ .., _, _] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_const_index_end_and_subslice() {
+    let a = array();
+    let [.., _x] = a;
+    let [_, _, _y @ ..] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_const_index_field_and_subslice() {
+    let a = array();
+    let [(_x, _), _, _] = a;
+    let [_y @ .., _, _] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_const_index_end_field_and_subslice() {
+    let a = array();
+    let [.., (_x, _)] = a;
+    let [_, _, _y @ ..] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_subslice_and_const_index_field() {
+    let a = array();
+    let [_y @ .., _, _] = a;
+    let [(_x, _), _, _] = a; //~ ERROR [E0382]
+}
+
+fn move_out_by_subslice_and_const_index_end_field() {
+    let a = array();
+    let [_, _, _y @ ..] = a;
+    let [.., (_x, _)] = a; //~ ERROR [E0382]
+}
+
+// Slice + Slice
+
+fn move_out_by_subslice_and_subslice() {
+    let a = array();
+    let [x @ .., _] = a;
+    let [_, _y @ ..] = a; //~ ERROR [E0382]
 }
 
 fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
index b34c03e..08134a2 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
@@ -1,23 +1,103 @@
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array.rs:7:14
+  --> $DIR/borrowck-move-out-from-array.rs:12:14
    |
-LL |     let [_, _x] = a;
-   |             -- value moved here
+LL |     let [_, _, _x] = a;
+   |                -- value moved here
 LL |     let [.., _y] = a;
    |              ^^ value used here after move
    |
-   = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array.rs:13:10
+  --> $DIR/borrowck-move-out-from-array.rs:18:14
    |
-LL |     let [_x, _] = a;
-   |          -- value moved here
-LL |     let [_y @ ..] = a;
-   |          ^^^^^^^ value used here after move
+LL |     let [_, _, (_x, _)] = a;
+   |                 -- value moved here
+LL |     let [.., _y] = a;
+   |              ^^ value used here after partial move
    |
-   = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
-error: aborting due to 2 previous errors
+error[E0382]: use of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array.rs:24:15
+   |
+LL |     let [_, _, (_x, _)] = a;
+   |                 -- value moved here
+LL |     let [.., (_y, _)] = a;
+   |               ^^ value used here after move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array.rs:32:10
+   |
+LL |     let [_x, _, _] = a;
+   |          -- value moved here
+LL |     let [_y @ .., _, _] = a;
+   |          ^^^^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array.rs:38:16
+   |
+LL |     let [.., _x] = a;
+   |              -- value moved here
+LL |     let [_, _, _y @ ..] = a;
+   |                ^^^^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array.rs:44:10
+   |
+LL |     let [(_x, _), _, _] = a;
+   |           -- value moved here
+LL |     let [_y @ .., _, _] = a;
+   |          ^^^^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array.rs:50:16
+   |
+LL |     let [.., (_x, _)] = a;
+   |               -- value moved here
+LL |     let [_, _, _y @ ..] = a;
+   |                ^^^^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array.rs:56:11
+   |
+LL |     let [_y @ .., _, _] = a;
+   |          ------- value moved here
+LL |     let [(_x, _), _, _] = a;
+   |           ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a[..].0`
+  --> $DIR/borrowck-move-out-from-array.rs:62:15
+   |
+LL |     let [_, _, _y @ ..] = a;
+   |                ------- value moved here
+LL |     let [.., (_x, _)] = a;
+   |               ^^ value used here after move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-move-out-from-array.rs:70:13
+   |
+LL |     let [x @ .., _] = a;
+   |          ------ value moved here
+LL |     let [_, _y @ ..] = a;
+   |             ^^^^^^^ value used here after partial move
+   |
+   = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
+
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs
new file mode 100644
index 0000000..7d91a21
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs
@@ -0,0 +1,66 @@
+// check-pass
+
+#![feature(slice_patterns)]
+
+fn nop(_s: &[& i32]) {}
+fn nop_subslice(_s: &[i32]) {}
+
+fn const_index_ok(s: &mut [i32; 4]) {
+    let [ref first, ref second, _, ref fourth, ..] = *s;
+    let [_, _, ref mut third, ..] = *s;
+    nop(&[first, second, third, fourth]);
+}
+
+fn const_index_from_end_ok(s: &mut [i32; 4]) {
+    let [.., ref fourth, ref third, _, ref first] = *s;
+    let [.., ref mut second, _] = *s;
+    nop(&[first, second, third, fourth]);
+}
+
+fn const_index_mixed(s: &mut [i32; 6]) {
+    let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
+
+    let [ref mut from_begin0, ..] = *s;
+    nop(&[from_begin0, from_end1, from_end3, from_end4]);
+    let [_, ref mut from_begin1, ..] = *s;
+    nop(&[from_begin1, from_end1, from_end3, from_end4]);
+
+    let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s;
+
+    let [.., ref mut from_end1] = *s;
+    nop(&[from_begin0, from_begin1, from_begin3, from_end1]);
+    let [.., ref mut from_end2, _] = *s;
+    nop(&[from_begin0, from_begin1, from_begin3, from_end2]);
+    let [.., ref mut from_end4, _, _, _] = *s;
+    nop(&[from_begin0, from_begin1, from_begin3, from_end4]);
+}
+
+fn const_index_and_subslice_ok(s: &mut [i32; 4]) {
+    let [ref first, ref second, ..] = *s;
+    let [_, _, ref mut tail @ ..] = *s;
+    nop(&[first, second]);
+    nop_subslice(tail);
+}
+
+fn const_index_and_subslice_from_end_ok(s: &mut [i32; 4]) {
+    let [.., ref second, ref first] = *s;
+    let [ref mut tail @ .., _, _] = *s;
+    nop(&[first, second]);
+    nop_subslice(tail);
+}
+
+fn subslices(s: &mut [i32; 4]) {
+    let [_, _, ref s1 @ ..] = *s;
+    let [ref mut s2 @ .., _, _] = *s;
+    nop_subslice(s1);
+    nop_subslice(s2);
+}
+
+fn main() {
+    let mut v = [1,2,3,4];
+    const_index_ok(&mut v);
+    const_index_from_end_ok(&mut v);
+    const_index_and_subslice_ok(&mut v);
+    const_index_and_subslice_from_end_ok(&mut v);
+    subslices(&mut v);
+}
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs
new file mode 100644
index 0000000..f03a2ab
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs
@@ -0,0 +1,60 @@
+#![feature(slice_patterns)]
+
+fn nop(_s: &[& i32]) {}
+fn nop_subslice(_s: &[i32]) {}
+
+fn const_index_err(s: &mut [i32; 4]) {
+    let [ref first, ref second, ..] = *s;
+    let [_, ref mut  second2, ref mut third, ..] = *s; //~ERROR
+    nop(&[first, second, second2, third]);
+}
+
+fn const_index_from_end_err(s: &mut [i32; 4]) {
+    let [.., ref fourth, ref third, _, ref first] = *s;
+    let [.., ref mut third2, _, _] = *s; //~ERROR
+    nop(&[first, third, third2, fourth]);
+}
+
+fn const_index_mixed(s: &mut [i32; 6]) {
+    let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
+
+    let [_, _, ref mut from_begin2, ..] = *s; //~ERROR
+    nop(&[from_begin2, from_end1, from_end3, from_end4]);
+    let [_, _, _, ref mut from_begin3, ..] = *s; //~ERROR
+    nop(&[from_begin3, from_end1, from_end3, from_end4]);
+
+    let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s;
+
+    let [.., ref mut from_end3, _,  _] = *s; //~ERROR
+    nop(&[from_begin0, from_begin1, from_begin3, from_end3]);
+}
+
+fn const_index_and_subslice_err(s: &mut [i32; 4]) {
+    let [ref first, ref second, ..] = *s;
+    let [_, ref mut tail @ ..] = *s; //~ERROR
+    nop(&[first, second]);
+    nop_subslice(tail);
+}
+
+fn const_index_and_subslice_from_end_err(s: &mut [i32; 4]) {
+    let [.., ref second, ref first] = *s;
+    let [ref mut tail @ .., _] = *s; //~ERROR
+    nop(&[first, second]);
+    nop_subslice(tail);
+}
+
+fn subslices_overlap(s: &mut [i32; 4]) {
+    let [_,  ref s1 @ ..] = *s;
+    let [ref mut s2 @ .., _, _] = *s; //~ERROR
+    nop_subslice(s1);
+    nop_subslice(s2);
+}
+
+fn main() {
+    let mut v = [1,2,3,4];
+    const_index_err(&mut v);
+    const_index_from_end_err(&mut v);
+    const_index_and_subslice_err(&mut v);
+    const_index_and_subslice_from_end_err(&mut v);
+    subslices_overlap(&mut v);
+}
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr
new file mode 100644
index 0000000..e50e7eb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr
@@ -0,0 +1,86 @@
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:8:13
+   |
+LL |     let [ref first, ref second, ..] = *s;
+   |                     ---------- immutable borrow occurs here
+LL |     let [_, ref mut  second2, ref mut third, ..] = *s;
+   |             ^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     nop(&[first, second, second2, third]);
+   |                  ------ immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:14:14
+   |
+LL |     let [.., ref fourth, ref third, _, ref first] = *s;
+   |                          --------- immutable borrow occurs here
+LL |     let [.., ref mut third2, _, _] = *s;
+   |              ^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     nop(&[first, third, third2, fourth]);
+   |                  ----- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:21:16
+   |
+LL |     let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
+   |                 ------------- immutable borrow occurs here
+LL | 
+LL |     let [_, _, ref mut from_begin2, ..] = *s;
+   |                ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     nop(&[from_begin2, from_end1, from_end3, from_end4]);
+   |                                              --------- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:23:19
+   |
+LL |     let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
+   |                                ------------- immutable borrow occurs here
+...
+LL |     let [_, _, _, ref mut from_begin3, ..] = *s;
+   |                   ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     nop(&[from_begin3, from_end1, from_end3, from_end4]);
+   |                                   --------- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:28:14
+   |
+LL |     let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s;
+   |                                               --------------- immutable borrow occurs here
+LL | 
+LL |     let [.., ref mut from_end3, _,  _] = *s;
+   |              ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     nop(&[from_begin0, from_begin1, from_begin3, from_end3]);
+   |                                     ----------- immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:34:13
+   |
+LL |     let [ref first, ref second, ..] = *s;
+   |                     ---------- immutable borrow occurs here
+LL |     let [_, ref mut tail @ ..] = *s;
+   |             ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     nop(&[first, second]);
+   |                  ------ immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:41:10
+   |
+LL |     let [.., ref second, ref first] = *s;
+   |              ---------- immutable borrow occurs here
+LL |     let [ref mut tail @ .., _] = *s;
+   |          ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     nop(&[first, second]);
+   |                  ------ immutable borrow later used here
+
+error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:48:10
+   |
+LL |     let [_,  ref s1 @ ..] = *s;
+   |              ----------- immutable borrow occurs here
+LL |     let [ref mut s2 @ .., _, _] = *s;
+   |          ^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     nop_subslice(s1);
+   |                  -- immutable borrow later used here
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs
new file mode 100644
index 0000000..e69071f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs
@@ -0,0 +1,61 @@
+// check-pass
+
+#![feature(slice_patterns)]
+
+fn nop(_s: &[& i32]) {}
+fn nop_subslice(_s: &[i32]) {}
+
+fn const_index_ok(s: &mut [i32]) {
+    if let [ref first, ref second, _, ref fourth, ..] = *s {
+        if let [_, _, ref mut third, ..] = *s {
+            nop(&[first, second, third, fourth]);
+        }
+    }
+}
+
+fn const_index_from_end_ok(s: &mut [i32]) {
+    if let [.., ref fourth, ref third, _, ref first] = *s {
+        if let [.., ref mut second, _] = *s {
+            nop(&[first, second, third, fourth]);
+        }
+    }
+}
+
+fn const_index_mixed(s: &mut [i32]) {
+    if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
+        if let [ref mut from_begin0, ..] = *s {
+            nop(&[from_begin0, from_end1, from_end3, from_end4]);
+        }
+    }
+    if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
+        if let [.., ref mut from_end1] = *s {
+            nop(&[from_begin0, from_begin1, from_begin3, from_end1]);
+        }
+    }
+}
+
+fn const_index_and_subslice_ok(s: &mut [i32]) {
+    if let [ref first, ref second, ..] = *s {
+        if let [_, _, ref mut tail @ ..] = *s {
+            nop(&[first, second]);
+            nop_subslice(tail);
+        }
+    }
+}
+
+fn const_index_and_subslice_from_end_ok(s: &mut [i32]) {
+    if let [.., ref second, ref first] = *s {
+        if let [ref mut tail @ .., _, _] = *s {
+            nop(&[first, second]);
+            nop_subslice(tail);
+        }
+    }
+}
+
+fn main() {
+    let mut v = [1,2,3,4];
+    const_index_ok(&mut v);
+    const_index_from_end_ok(&mut v);
+    const_index_and_subslice_ok(&mut v);
+    const_index_and_subslice_from_end_ok(&mut v);
+}
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
similarity index 65%
rename from src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs
rename to src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
index a6b54f9..2ef9874 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
@@ -1,18 +1,8 @@
-//compile-flags: -Z borrowck=mir
-
 #![feature(slice_patterns)]
 
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
-fn const_index_ok(s: &mut [i32]) {
-    if let [ref first, ref second, _, ref fourth, ..] = *s {
-        if let [_, _, ref mut third, ..] = *s {
-            nop(&[first, second, third, fourth]);
-        }
-    }
-}
-
 fn const_index_err(s: &mut [i32]) {
     if let [ref first, ref second, ..] = *s {
         if let [_, ref mut  second2, ref mut third, ..] = *s { //~ERROR
@@ -21,14 +11,6 @@
     }
 }
 
-fn const_index_from_end_ok(s: &mut [i32]) {
-    if let [.., ref fourth, ref third, _, ref first] = *s {
-        if let [.., ref mut second, _] = *s {
-            nop(&[first, second, third, fourth]);
-        }
-    }
-}
-
 fn const_index_from_end_err(s: &mut [i32]) {
     if let [.., ref fourth, ref third, _, ref first] = *s {
         if let [.., ref mut third2, _, _] = *s { //~ERROR
@@ -39,9 +21,6 @@
 
 fn const_index_mixed(s: &mut [i32]) {
     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
-        if let [ref mut from_begin0, ..] = *s {
-            nop(&[from_begin0, from_end1, from_end3, from_end4]);
-        }
         if let [_, ref mut from_begin1, ..] = *s { //~ERROR
             nop(&[from_begin1, from_end1, from_end3, from_end4]);
         }
@@ -53,9 +32,6 @@
         }
     }
     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
-        if let [.., ref mut from_end1] = *s {
-            nop(&[from_begin0, from_begin1, from_begin3, from_end1]);
-        }
         if let [.., ref mut from_end2, _] = *s { //~ERROR
             nop(&[from_begin0, from_begin1, from_begin3, from_end2]);
         }
@@ -68,15 +44,6 @@
     }
 }
 
-fn const_index_and_subslice_ok(s: &mut [i32]) {
-    if let [ref first, ref second, ..] = *s {
-        if let [_, _, ref mut tail @ ..] = *s {
-            nop(&[first, second]);
-            nop_subslice(tail);
-        }
-    }
-}
-
 fn const_index_and_subslice_err(s: &mut [i32]) {
     if let [ref first, ref second, ..] = *s {
         if let [_, ref mut tail @ ..] = *s { //~ERROR
@@ -86,15 +53,6 @@
     }
 }
 
-fn const_index_and_subslice_from_end_ok(s: &mut [i32]) {
-    if let [.., ref second, ref first] = *s {
-        if let [ref mut tail @ .., _, _] = *s {
-            nop(&[first, second]);
-            nop_subslice(tail);
-        }
-    }
-}
-
 fn const_index_and_subslice_from_end_err(s: &mut [i32]) {
     if let [.., ref second, ref first] = *s {
         if let [ref mut tail @ .., _] = *s { //~ERROR
@@ -115,13 +73,9 @@
 
 fn main() {
     let mut v = [1,2,3,4];
-    const_index_ok(&mut v);
     const_index_err(&mut v);
-    const_index_from_end_ok(&mut v);
     const_index_from_end_err(&mut v);
-    const_index_and_subslice_ok(&mut v);
     const_index_and_subslice_err(&mut v);
-    const_index_and_subslice_from_end_ok(&mut v);
     const_index_and_subslice_from_end_err(&mut v);
     subslices(&mut v);
 }
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
similarity index 89%
rename from src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr
rename to src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
index 2c019f4..b6f5ac6 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:18:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:8:20
    |
 LL |     if let [ref first, ref second, ..] = *s {
    |                        ---------- immutable borrow occurs here
@@ -9,7 +9,7 @@
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:34:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:16:21
    |
 LL |     if let [.., ref fourth, ref third, _, ref first] = *s {
    |                             --------- immutable borrow occurs here
@@ -19,18 +19,17 @@
    |                          ----- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:45:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:24:20
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                    ------------- immutable borrow occurs here
-...
 LL |         if let [_, ref mut from_begin1, ..] = *s {
    |                    ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[from_begin1, from_end1, from_end3, from_end4]);
    |                                                      --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:48:23
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:27:23
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                                   ------------- immutable borrow occurs here
@@ -41,7 +40,7 @@
    |                                           --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:51:26
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:30:26
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                                   ------------- immutable borrow occurs here
@@ -52,18 +51,17 @@
    |                                           --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:59:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:35:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                                                  --------------- immutable borrow occurs here
-...
 LL |         if let [.., ref mut from_end2, _] = *s {
    |                     ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end2]);
    |                                             ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:62:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:38:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                                                  --------------- immutable borrow occurs here
@@ -74,7 +72,7 @@
    |                                             ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:65:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:41:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                              --------------- immutable borrow occurs here
@@ -85,7 +83,7 @@
    |                                ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:82:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:49:20
    |
 LL |     if let [ref first, ref second, ..] = *s {
    |                        ---------- immutable borrow occurs here
@@ -95,7 +93,7 @@
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:100:17
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:58:17
    |
 LL |     if let [.., ref second, ref first] = *s {
    |                 ---------- immutable borrow occurs here
@@ -105,7 +103,7 @@
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan.rs:109:17
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:67:17
    |
 LL |     if let [_, _, _, ref s1 @ ..] = *s {
    |                      ----------- immutable borrow occurs here
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr
index c80ed5e..cd4cd8b 100644
--- a/src/test/ui/c-variadic/variadic-ffi-4.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr
@@ -49,9 +49,13 @@
    |
 LL |     let _ = ap.with_copy(|ap| { ap });
    |                          ^^^^^^^^^^^
-   = note: ...so that the expression is assignable:
-           expected core::ffi::VaList<'_, '_>
-              found core::ffi::VaList<'_, '_>
+note: ...so that the expression is assignable
+  --> $DIR/variadic-ffi-4.rs:16:33
+   |
+LL |     let _ = ap.with_copy(|ap| { ap });
+   |                                 ^^
+   = note: expected  `core::ffi::VaList<'_, '_>`
+              found  `core::ffi::VaList<'_, '_>`
 note: but, the lifetime must be valid for the method call at 16:13...
   --> $DIR/variadic-ffi-4.rs:16:13
    |
diff --git a/src/test/ui/check-static-immutable-mut-slices.stderr b/src/test/ui/check-static-immutable-mut-slices.stderr
index 4f4bf16..39da824 100644
--- a/src/test/ui/check-static-immutable-mut-slices.stderr
+++ b/src/test/ui/check-static-immutable-mut-slices.stderr
@@ -1,9 +1,12 @@
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
   --> $DIR/check-static-immutable-mut-slices.rs:3:37
    |
 LL | static TEST: &'static mut [isize] = &mut [];
    |                                     ^^^^^^^ statics require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0017`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr
index a6b52b2..7141c04 100644
--- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr
@@ -39,3 +39,4 @@
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
index a154442..0033395 100644
--- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
@@ -77,4 +77,5 @@
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0308, E0631.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
index 9fbe95a..1c6564e 100644
--- a/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
+++ b/src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
@@ -13,3 +13,4 @@
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.polonius.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.polonius.stderr
new file mode 100644
index 0000000..2a7461f
--- /dev/null
+++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.polonius.stderr
@@ -0,0 +1,56 @@
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/expect-region-supply-region.rs:18:9
+   |
+LL |     let mut f: Option<&u32> = None;
+   |         ----- `f` is declared here, outside of the closure body
+LL |     closure_expecting_bound(|x| {
+   |                              - `x` is a reference that is only valid in the closure body
+LL |         f = Some(x);
+   |         ^^^^^^^^^^^ `x` escapes the closure body here
+
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/expect-region-supply-region.rs:28:9
+   |
+LL |     let mut f: Option<&u32> = None;
+   |         ----- `f` is declared here, outside of the closure body
+LL |     closure_expecting_bound(|x: &u32| {
+   |                              - `x` is a reference that is only valid in the closure body
+LL |         f = Some(x);
+   |         ^^^^^^^^^^^ `x` escapes the closure body here
+
+error: lifetime may not live long enough
+  --> $DIR/expect-region-supply-region.rs:37:30
+   |
+LL | fn expect_bound_supply_named<'x>() {
+   |                              -- lifetime `'x` defined here
+...
+LL |     closure_expecting_bound(|x: &'x u32| {
+   |                              ^  - let's call the lifetime of this reference `'1`
+   |                              |
+   |                              requires that `'1` must outlive `'x`
+
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/expect-region-supply-region.rs:42:9
+   |
+LL |     let mut f: Option<&u32> = None;
+   |         ----- `f` is declared here, outside of the closure body
+...
+LL |     closure_expecting_bound(|x: &'x u32| {
+   |                              - `x` is a reference that is only valid in the closure body
+...
+LL |         f = Some(x);
+   |         ^^^^^^^^^^^ `x` escapes the closure body here
+
+error: lifetime may not live long enough
+  --> $DIR/expect-region-supply-region.rs:37:30
+   |
+LL | fn expect_bound_supply_named<'x>() {
+   |                              -- lifetime `'x` defined here
+...
+LL |     closure_expecting_bound(|x: &'x u32| {
+   |                              ^ requires that `'x` must outlive `'static`
+   |
+   = help: consider replacing `'x` with `'static`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr
index 91d26ef..2f2871e 100644
--- a/src/test/ui/closures/issue-41366.stderr
+++ b/src/test/ui/closures/issue-41366.stderr
@@ -19,4 +19,5 @@
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/closures/issue-67123.rs b/src/test/ui/closures/issue-67123.rs
new file mode 100644
index 0000000..014c530
--- /dev/null
+++ b/src/test/ui/closures/issue-67123.rs
@@ -0,0 +1,5 @@
+fn foo<T>(t: T) {
+    || { t; t; }; //~ ERROR: use of moved value
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/issue-67123.stderr b/src/test/ui/closures/issue-67123.stderr
new file mode 100644
index 0000000..b2e875b
--- /dev/null
+++ b/src/test/ui/closures/issue-67123.stderr
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value: `t`
+  --> $DIR/issue-67123.rs:2:13
+   |
+LL | fn foo<T>(t: T) {
+   |        - help: consider restricting this bound: `T: Copy`
+LL |     || { t; t; };
+   |          -  ^ value used here after move
+   |          |
+   |          value moved here
+   |
+   = note: move occurs because `t` has type `T`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.rs b/src/test/ui/conditional-compilation/cfg-attr-parse.rs
index 93aef72..8ca31c1 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-parse.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-parse.rs
@@ -1,11 +1,11 @@
 // Parse `cfg_attr` with varying numbers of attributes and trailing commas
 
 // Completely empty `cfg_attr` input
-#[cfg_attr()] //~ error: expected identifier, found `)`
+#[cfg_attr()] //~ error: malformed `cfg_attr` attribute input
 struct NoConfigurationPredicate;
 
 // Zero attributes, zero trailing comma (comma manatory here)
-#[cfg_attr(all())] //~ error: expected `,`, found `)`
+#[cfg_attr(all())] //~ error: expected `,`, found end of `cfg_attr`
 struct A0C0;
 
 // Zero attributes, one trailing comma
@@ -40,4 +40,16 @@
 #[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
 struct A2C2;
 
+// Wrong delimiter `[`
+#[cfg_attr[all(),,]]
+//~^ ERROR wrong `cfg_attr` delimiters
+//~| ERROR expected identifier, found `,`
+struct BracketZero;
+
+// Wrong delimiter `{`
+#[cfg_attr{all(),,}]
+//~^ ERROR wrong `cfg_attr` delimiters
+//~| ERROR expected identifier, found `,`
+struct BraceZero;
+
 fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
index 3dfbd6d..3a590d3 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
@@ -1,32 +1,86 @@
-error: expected identifier, found `)`
-  --> $DIR/cfg-attr-parse.rs:4:12
+error: malformed `cfg_attr` attribute input
+  --> $DIR/cfg-attr-parse.rs:4:1
    |
 LL | #[cfg_attr()]
-   |            ^ expected identifier
+   | ^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
 
-error: expected `,`, found `)`
+error: expected `,`, found end of `cfg_attr` input
   --> $DIR/cfg-attr-parse.rs:8:17
    |
 LL | #[cfg_attr(all())]
    |                 ^ expected `,`
+   |
+   = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
 
 error: expected identifier, found `,`
   --> $DIR/cfg-attr-parse.rs:16:18
    |
 LL | #[cfg_attr(all(),,)]
    |                  ^ expected identifier
+   |
+   = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
 
 error: expected identifier, found `,`
   --> $DIR/cfg-attr-parse.rs:28:28
    |
 LL | #[cfg_attr(all(), must_use,,)]
    |                            ^ expected identifier
+   |
+   = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
 
 error: expected identifier, found `,`
   --> $DIR/cfg-attr-parse.rs:40:40
    |
 LL | #[cfg_attr(all(), must_use, deprecated,,)]
    |                                        ^ expected identifier
+   |
+   = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
 
-error: aborting due to 5 previous errors
+error: wrong `cfg_attr` delimiters
+  --> $DIR/cfg-attr-parse.rs:44:11
+   |
+LL | #[cfg_attr[all(),,]]
+   |           ^^^^^^^^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL | #[cfg_attr(all(),,)]
+   |           ^       ^
+
+error: expected identifier, found `,`
+  --> $DIR/cfg-attr-parse.rs:44:18
+   |
+LL | #[cfg_attr[all(),,]]
+   |                  ^ expected identifier
+   |
+   = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+error: wrong `cfg_attr` delimiters
+  --> $DIR/cfg-attr-parse.rs:50:11
+   |
+LL | #[cfg_attr{all(),,}]
+   |           ^^^^^^^^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL | #[cfg_attr(all(),,)]
+   |           ^       ^
+
+error: expected identifier, found `,`
+  --> $DIR/cfg-attr-parse.rs:50:18
+   |
+LL | #[cfg_attr{all(),,}]
+   |                  ^ expected identifier
+   |
+   = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.stderr b/src/test/ui/const-generics/cannot-infer-const-args.stderr
index 32adc63..8379cbd 100644
--- a/src/test/ui/const-generics/cannot-infer-const-args.stderr
+++ b/src/test/ui/const-generics/cannot-infer-const-args.stderr
@@ -10,7 +10,7 @@
   --> $DIR/cannot-infer-const-args.rs:9:5
    |
 LL |     foo();
-   |     ^^^ cannot infer type for `fn() -> usize {foo::<_: usize>}`
+   |     ^^^ cannot infer type for fn item `fn() -> usize {foo::<_: usize>}`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr
index 2d9b6ed..9ccad7b 100644
--- a/src/test/ui/const-generics/fn-const-param-infer.stderr
+++ b/src/test/ui/const-generics/fn-const-param-infer.stderr
@@ -30,7 +30,7 @@
   --> $DIR/fn-const-param-infer.rs:22:23
    |
 LL |     let _ = Checked::<generic>;
-   |                       ^^^^^^^ cannot infer type for `T`
+   |                       ^^^^^^^ cannot infer type for type parameter `T`
 
 error[E0308]: mismatched types
   --> $DIR/fn-const-param-infer.rs:25:40
diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr
index 0ddc2a0..f4d4e6f 100644
--- a/src/test/ui/consts/array-literal-index-oob.stderr
+++ b/src/test/ui/consts/array-literal-index-oob.stderr
@@ -12,7 +12,7 @@
 LL |     &{[1, 2, 3][4]};
    |     --^^^^^^^^^^^^-
    |       |
-   |       index out of bounds: the len is 3 but the index is 4
+   |       indexing out of bounds: the len is 3 but the index is 4
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/assoc_const_generic_impl.rs b/src/test/ui/consts/assoc_const_generic_impl.rs
new file mode 100644
index 0000000..62702a8
--- /dev/null
+++ b/src/test/ui/consts/assoc_const_generic_impl.rs
@@ -0,0 +1,19 @@
+#![warn(const_err)]
+
+trait ZeroSized: Sized {
+    const I_AM_ZERO_SIZED: ();
+    fn requires_zero_size(self);
+}
+
+impl<T: Sized> ZeroSized for T {
+    const I_AM_ZERO_SIZED: ()  = [()][std::mem::size_of::<Self>()]; //~ WARN any use of this value
+    fn requires_zero_size(self) {
+        let () = Self::I_AM_ZERO_SIZED; //~ ERROR erroneous constant encountered
+        println!("requires_zero_size called");
+    }
+}
+
+fn main() {
+    ().requires_zero_size();
+    42_u32.requires_zero_size();
+}
diff --git a/src/test/ui/consts/assoc_const_generic_impl.stderr b/src/test/ui/consts/assoc_const_generic_impl.stderr
new file mode 100644
index 0000000..a114d5c
--- /dev/null
+++ b/src/test/ui/consts/assoc_const_generic_impl.stderr
@@ -0,0 +1,22 @@
+warning: any use of this value will cause an error
+  --> $DIR/assoc_const_generic_impl.rs:9:34
+   |
+LL |     const I_AM_ZERO_SIZED: ()  = [()][std::mem::size_of::<Self>()];
+   |     -----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                  |
+   |                                  index out of bounds: the len is 1 but the index is 4
+   |
+note: lint level defined here
+  --> $DIR/assoc_const_generic_impl.rs:1:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+error: erroneous constant encountered
+  --> $DIR/assoc_const_generic_impl.rs:11:18
+   |
+LL |         let () = Self::I_AM_ZERO_SIZED;
+   |                  ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs
index e5ee90f..ecbcc2a 100644
--- a/src/test/ui/consts/const-err2.rs
+++ b/src/test/ui/consts/const-err2.rs
@@ -23,7 +23,6 @@
     //~^ ERROR const_err
     let _e = [5u8][1];
     //~^ ERROR index out of bounds
-    //~| ERROR this expression will panic at runtime
     black_box(a);
     black_box(b);
     black_box(c);
diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr
index 0a09a72..1d84d44 100644
--- a/src/test/ui/consts/const-err2.stderr
+++ b/src/test/ui/consts/const-err2.stderr
@@ -34,11 +34,5 @@
 LL |     let _e = [5u8][1];
    |              ^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:24:14
-   |
-LL |     let _e = [5u8][1];
-   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs
index 89373f9..a9cf04c 100644
--- a/src/test/ui/consts/const-err3.rs
+++ b/src/test/ui/consts/const-err3.rs
@@ -23,7 +23,6 @@
     //~^ ERROR const_err
     let _e = [5u8][1];
     //~^ ERROR const_err
-    //~| ERROR this expression will panic at runtime
     black_box(a);
     black_box(b);
     black_box(c);
diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr
index 42de247..0602707 100644
--- a/src/test/ui/consts/const-err3.stderr
+++ b/src/test/ui/consts/const-err3.stderr
@@ -34,11 +34,5 @@
 LL |     let _e = [5u8][1];
    |              ^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/const-err3.rs:24:14
-   |
-LL |     let _e = [5u8][1];
-   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/consts/const-eval/const_caller_location.rs b/src/test/ui/consts/const-eval/const_caller_location.rs
deleted file mode 100644
index c63822f..0000000
--- a/src/test/ui/consts/const-eval/const_caller_location.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-
-#![feature(const_fn, core_intrinsics)]
-
-use std::{intrinsics::caller_location, panic::Location};
-
-const LOCATION: &Location = caller_location();
-const NESTED: &Location = {
-    const fn nested_location() -> &'static Location<'static> {
-        caller_location()
-    };
-    nested_location()
-};
-
-fn main() {
-    assert_eq!(LOCATION.file(), file!());
-    assert_eq!(LOCATION.line(), 7);
-    assert_eq!(LOCATION.column(), 29);
-
-    assert_eq!(NESTED.file(), file!());
-    assert_eq!(NESTED.line(), 10);
-    assert_eq!(NESTED.column(), 9);
-}
diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
new file mode 100644
index 0000000..516ca4f
--- /dev/null
+++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
@@ -0,0 +1,18 @@
+// Regression test for #66975
+#![warn(const_err)]
+
+struct PrintName<T>(T);
+
+impl<T> PrintName<T> {
+    const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
+    //~^ WARN any use of this value will cause an error
+}
+
+fn f<T>() {
+    let _ = PrintName::<T>::VOID;
+    //~^ ERROR erroneous constant encountered
+}
+
+pub fn main() {
+    f::<()>();
+}
diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
new file mode 100644
index 0000000..e2bd8d0
--- /dev/null
+++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
@@ -0,0 +1,22 @@
+warning: any use of this value will cause an error
+  --> $DIR/index-out-of-bounds-never-type.rs:7:61
+   |
+LL |     const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
+   |     --------------------------------------------------------^^^^^---
+   |                                                             |
+   |                                                             index out of bounds: the len is 0 but the index is 0
+   |
+note: lint level defined here
+  --> $DIR/index-out-of-bounds-never-type.rs:2:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+error: erroneous constant encountered
+  --> $DIR/index-out-of-bounds-never-type.rs:12:13
+   |
+LL |     let _ = PrintName::<T>::VOID;
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr
index acf5cba..54b3507 100644
--- a/src/test/ui/consts/const-eval/issue-65394.stderr
+++ b/src/test/ui/consts/const-eval/issue-65394.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
   --> $DIR/issue-65394.rs:8:13
    |
 LL |     let r = &mut x;
    |             ^^^^^^ constants require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/issue-65394.rs:7:9
@@ -12,5 +15,5 @@
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0017, E0493.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0493, E0658.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.rs b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs
new file mode 100644
index 0000000..b39d9af
--- /dev/null
+++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs
@@ -0,0 +1,15 @@
+// Regression test for #66975
+#![warn(const_err)]
+#![feature(const_panic)]
+
+struct PrintName;
+
+impl PrintName {
+    const VOID: ! = panic!();
+    //~^ WARN any use of this value will cause an error
+}
+
+fn main() {
+    let _ = PrintName::VOID;
+    //~^ ERROR erroneous constant used
+}
diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
new file mode 100644
index 0000000..c07c8c6
--- /dev/null
+++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
@@ -0,0 +1,24 @@
+warning: any use of this value will cause an error
+  --> $DIR/panic-assoc-never-type.rs:8:21
+   |
+LL |     const VOID: ! = panic!();
+   |     ----------------^^^^^^^^-
+   |                     |
+   |                     the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:8:21
+   |
+note: lint level defined here
+  --> $DIR/panic-assoc-never-type.rs:2:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: erroneous constant used
+  --> $DIR/panic-assoc-never-type.rs:13:13
+   |
+LL |     let _ = PrintName::VOID;
+   |             ^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/panic-never-type.rs b/src/test/ui/consts/const-eval/panic-never-type.rs
new file mode 100644
index 0000000..42eabbf
--- /dev/null
+++ b/src/test/ui/consts/const-eval/panic-never-type.rs
@@ -0,0 +1,11 @@
+// Regression test for #66975
+#![warn(const_err)]
+#![feature(const_panic)]
+
+const VOID: ! = panic!();
+//~^ WARN any use of this value will cause an error
+
+fn main() {
+    let _ = VOID;
+    //~^ ERROR erroneous constant used
+}
diff --git a/src/test/ui/consts/const-eval/panic-never-type.stderr b/src/test/ui/consts/const-eval/panic-never-type.stderr
new file mode 100644
index 0000000..4fb11a6
--- /dev/null
+++ b/src/test/ui/consts/const-eval/panic-never-type.stderr
@@ -0,0 +1,24 @@
+warning: any use of this value will cause an error
+  --> $DIR/panic-never-type.rs:5:17
+   |
+LL | const VOID: ! = panic!();
+   | ----------------^^^^^^^^-
+   |                 |
+   |                 the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:5:17
+   |
+note: lint level defined here
+  --> $DIR/panic-never-type.rs:2:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+   = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: erroneous constant used
+  --> $DIR/panic-never-type.rs:9:13
+   |
+LL |     let _ = VOID;
+   |             ^^^^ referenced constant has errors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs
index 4594139..dfa6863 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs
@@ -8,14 +8,12 @@
     //~^ ERROR const_err
     println!("{}", 1/(1-1));
     //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR reaching this expression at runtime will panic or abort [const_err]
+    //~| ERROR const_err
     let _x = 1/(1-1);
     //~^ ERROR const_err
-    //~| ERROR const_err
     println!("{}", 1/(false as u32));
     //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR reaching this expression at runtime will panic or abort [const_err]
+    //~| ERROR const_err
     let _x = 1/(false as u32);
     //~^ ERROR const_err
-    //~| ERROR const_err
 }
diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr
index 40d5c73..848a880 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.stderr
@@ -20,7 +20,7 @@
   --> $DIR/promoted_errors.rs:9:20
    |
 LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^ attempt to divide by zero
+   |                    ^^^^^^^ dividing by zero
 
 error: attempt to divide by zero
   --> $DIR/promoted_errors.rs:12:14
@@ -28,35 +28,23 @@
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/promoted_errors.rs:12:14
-   |
-LL |     let _x = 1/(1-1);
-   |              ^^^^^^^ attempt to divide by zero
-
 error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:15:20
+  --> $DIR/promoted_errors.rs:14:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^
 
 error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:15:20
+  --> $DIR/promoted_errors.rs:14:20
    |
 LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^ attempt to divide by zero
+   |                    ^^^^^^^^^^^^^^^^ dividing by zero
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:18:14
+  --> $DIR/promoted_errors.rs:17:14
    |
 LL |     let _x = 1/(false as u32);
    |              ^^^^^^^^^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/promoted_errors.rs:18:14
-   |
-LL |     let _x = 1/(false as u32);
-   |              ^^^^^^^^^^^^^^^^ attempt to divide by zero
-
-error: aborting due to 9 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs
index 7adb394..58b1794 100644
--- a/src/test/ui/consts/const-eval/promoted_errors2.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors2.rs
@@ -9,14 +9,12 @@
     //~^ ERROR attempt to subtract with overflow
     println!("{}", 1/(1-1));
     //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR reaching this expression at runtime will panic or abort [const_err]
+    //~| ERROR const_err
     let _x = 1/(1-1);
     //~^ ERROR const_err
-    //~| ERROR const_err
     println!("{}", 1/(false as u32));
     //~^ ERROR attempt to divide by zero [const_err]
-    //~| ERROR reaching this expression at runtime will panic or abort [const_err]
+    //~| ERROR const_err
     let _x = 1/(false as u32);
     //~^ ERROR const_err
-    //~| ERROR const_err
 }
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr
index 2819e6e..6f4b1c0 100644
--- a/src/test/ui/consts/const-eval/promoted_errors2.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr
@@ -26,7 +26,7 @@
   --> $DIR/promoted_errors2.rs:10:20
    |
 LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^ attempt to divide by zero
+   |                    ^^^^^^^ dividing by zero
 
 error: attempt to divide by zero
   --> $DIR/promoted_errors2.rs:13:14
@@ -34,35 +34,23 @@
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/promoted_errors2.rs:13:14
-   |
-LL |     let _x = 1/(1-1);
-   |              ^^^^^^^ attempt to divide by zero
-
 error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:16:20
+  --> $DIR/promoted_errors2.rs:15:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^
 
 error: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:16:20
+  --> $DIR/promoted_errors2.rs:15:20
    |
 LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^ attempt to divide by zero
+   |                    ^^^^^^^^^^^^^^^^ dividing by zero
 
 error: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:19:14
+  --> $DIR/promoted_errors2.rs:18:14
    |
 LL |     let _x = 1/(false as u32);
    |              ^^^^^^^^^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/promoted_errors2.rs:19:14
-   |
-LL |     let _x = 1/(false as u32);
-   |              ^^^^^^^^^^^^^^^^ attempt to divide by zero
-
-error: aborting due to 10 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr
index ed3837e..0809c77 100644
--- a/src/test/ui/consts/const-multi-ref.stderr
+++ b/src/test/ui/consts/const-multi-ref.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
   --> $DIR/const-multi-ref.rs:6:13
    |
 LL |     let p = &mut a;
    |             ^^^^^^ constants require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
   --> $DIR/const-multi-ref.rs:16:13
@@ -12,5 +15,5 @@
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0017, E0492.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0492, E0658.
+For more information about an error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
new file mode 100644
index 0000000..33abfec
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
@@ -0,0 +1,37 @@
+// run-pass
+
+#![feature(const_mut_refs)]
+#![feature(const_fn)]
+
+struct Foo {
+    x: usize
+}
+
+const fn foo() -> Foo {
+    Foo { x: 0 }
+}
+
+impl Foo {
+    const fn bar(&mut self) -> usize {
+        self.x = 1;
+        self.x
+    }
+
+}
+
+const fn baz(foo: &mut Foo) -> usize {
+    let x = &mut foo.x;
+    *x = 2;
+    *x
+}
+
+const fn bazz(foo: &mut Foo) -> usize {
+    foo.x = 3;
+    foo.x
+}
+
+fn main() {
+    let _: [(); foo().bar()] = [(); 1];
+    let _: [(); baz(&mut foo())] = [(); 2];
+    let _: [(); bazz(&mut foo())] = [(); 3];
+}
diff --git a/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs
new file mode 100644
index 0000000..2207599
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs
@@ -0,0 +1,7 @@
+fn main() {
+    foo(&mut 5);
+}
+
+const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references in const fn are unstable
+    *x + 1
+}
diff --git a/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr
new file mode 100644
index 0000000..4fae119
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr
@@ -0,0 +1,12 @@
+error[E0723]: mutable references in const fn are unstable
+  --> $DIR/feature-gate-const_mut_refs.rs:5:14
+   |
+LL | const fn foo(x: &mut i32) -> i32 {
+   |              ^
+   |
+   = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs
index 48c4b7d..13309f9 100644
--- a/src/test/ui/consts/const-prop-ice.rs
+++ b/src/test/ui/consts/const-prop-ice.rs
@@ -1,4 +1,3 @@
 fn main() {
     [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
-    //~| ERROR this expression will panic at runtime
 }
diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr
index 8ecc6f4..4b38801 100644
--- a/src/test/ui/consts/const-prop-ice.stderr
+++ b/src/test/ui/consts/const-prop-ice.stderr
@@ -6,11 +6,5 @@
    |
    = note: `#[deny(const_err)]` on by default
 
-error: this expression will panic at runtime
-  --> $DIR/const-prop-ice.rs:2:5
-   |
-LL |     [0; 3][3u64 as usize];
-   |     ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
index 53b960b..7852874 100644
--- a/src/test/ui/consts/const_let_assign3.stderr
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -4,17 +4,23 @@
 LL |         self.state = x;
    |         ^^^^^^^^^^^^^^
 
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
   --> $DIR/const_let_assign3.rs:16:5
    |
 LL |     s.foo(3);
    |     ^ constants require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
   --> $DIR/const_let_assign3.rs:22:13
    |
 LL |     let y = &mut x;
    |             ^^^^^^ constants require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0019]: constant contains unimplemented expression type
   --> $DIR/const_let_assign3.rs:24:5
@@ -24,5 +30,5 @@
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0017, E0019.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/control-flow/basics.rs b/src/test/ui/consts/control-flow/basics.rs
index 8bd1929..b9ff040 100644
--- a/src/test/ui/consts/control-flow/basics.rs
+++ b/src/test/ui/consts/control-flow/basics.rs
@@ -4,6 +4,7 @@
 
 #![feature(const_panic)]
 #![feature(const_if_match)]
+#![feature(const_fn)]
 
 const X: u32 = 4;
 const Y: u32 = 5;
diff --git a/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs b/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
index 6bbbdd9..7887fd1 100644
--- a/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
+++ b/src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
@@ -3,6 +3,7 @@
 // check-pass
 
 #![feature(const_if_match)]
+#![feature(const_fn)]
 
 enum E {
     A,
diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr
index 21e3f2a..9509672 100644
--- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr
+++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr
@@ -1,5 +1,5 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/feature-gate-const-if-match.rs:108:1
+  --> $DIR/feature-gate-const-if-match.rs:109:1
    |
 LL | / fn main() {
 LL | |     let _ = [0; {
diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs
index 00576d5..e4b6525 100644
--- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs
+++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs
@@ -6,6 +6,7 @@
 
 #![feature(rustc_attrs)]
 #![cfg_attr(if_match, feature(const_if_match))]
+#![feature(const_fn)]
 
 const _: i32 = if true { //[stock]~ ERROR `if` is not allowed in a `const`
     5
diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr
index d3c6a51..e846ee4 100644
--- a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr
+++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr
@@ -1,5 +1,5 @@
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:10:16
+  --> $DIR/feature-gate-const-if-match.rs:11:16
    |
 LL |   const _: i32 = if true {
    |  ________________^
@@ -13,7 +13,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:16:16
+  --> $DIR/feature-gate-const-if-match.rs:17:16
    |
 LL |   const _: i32 = if let Some(true) = Some(false) {
    |  ________________^
@@ -27,7 +27,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:22:16
+  --> $DIR/feature-gate-const-if-match.rs:23:16
    |
 LL |   const _: i32 = match 1 {
    |  ________________^
@@ -41,7 +41,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static`
-  --> $DIR/feature-gate-const-if-match.rs:29:13
+  --> $DIR/feature-gate-const-if-match.rs:30:13
    |
 LL |     let x = if true { 0 } else { 1 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +50,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `static`
-  --> $DIR/feature-gate-const-if-match.rs:31:13
+  --> $DIR/feature-gate-const-if-match.rs:32:13
    |
 LL |     let x = match x { 0 => 1, _ => 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -59,7 +59,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static`
-  --> $DIR/feature-gate-const-if-match.rs:33:5
+  --> $DIR/feature-gate-const-if-match.rs:34:5
    |
 LL |     if let Some(x) = Some(x) { x } else { 1 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,7 +68,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static mut`
-  --> $DIR/feature-gate-const-if-match.rs:38:13
+  --> $DIR/feature-gate-const-if-match.rs:39:13
    |
 LL |     let x = if true { 0 } else { 1 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `static mut`
-  --> $DIR/feature-gate-const-if-match.rs:40:13
+  --> $DIR/feature-gate-const-if-match.rs:41:13
    |
 LL |     let x = match x { 0 => 1, _ => 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -86,7 +86,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `static mut`
-  --> $DIR/feature-gate-const-if-match.rs:42:5
+  --> $DIR/feature-gate-const-if-match.rs:43:5
    |
 LL |     if let Some(x) = Some(x) { x } else { 1 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:47:5
+  --> $DIR/feature-gate-const-if-match.rs:48:5
    |
 LL |     if true { 5 } else { 6 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +104,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:51:5
+  --> $DIR/feature-gate-const-if-match.rs:52:5
    |
 LL | /     if let Some(true) = a {
 LL | |         0
@@ -117,7 +117,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:59:5
+  --> $DIR/feature-gate-const-if-match.rs:60:5
    |
 LL | /     match i {
 LL | |         i if i > 10 => i,
@@ -130,7 +130,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:90:17
+  --> $DIR/feature-gate-const-if-match.rs:91:17
    |
 LL |         let x = if y { 0 } else { 1 };
    |                 ^^^^^^^^^^^^^^^^^^^^^
@@ -139,7 +139,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:92:17
+  --> $DIR/feature-gate-const-if-match.rs:93:17
    |
 LL |         let x = match x { 0 => 1, _ => 0 };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +148,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const fn`
-  --> $DIR/feature-gate-const-if-match.rs:94:9
+  --> $DIR/feature-gate-const-if-match.rs:95:9
    |
 LL |         if let Some(x) = Some(x) { x } else { 1 }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -157,7 +157,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:110:17
+  --> $DIR/feature-gate-const-if-match.rs:111:17
    |
 LL |         let x = if false { 0 } else { 1 };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,7 +166,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:112:17
+  --> $DIR/feature-gate-const-if-match.rs:113:17
    |
 LL |         let x = match x { 0 => 1, _ => 0 };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -175,7 +175,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:114:9
+  --> $DIR/feature-gate-const-if-match.rs:115:9
    |
 LL |         if let Some(x) = Some(x) { x } else { 1 }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -184,7 +184,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:67:21
+  --> $DIR/feature-gate-const-if-match.rs:68:21
    |
 LL |     const IF: i32 = if true { 5 } else { 6 };
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -193,7 +193,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:70:25
+  --> $DIR/feature-gate-const-if-match.rs:71:25
    |
 LL |     const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -202,7 +202,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:73:24
+  --> $DIR/feature-gate-const-if-match.rs:74:24
    |
 LL |     const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -211,7 +211,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:78:21
+  --> $DIR/feature-gate-const-if-match.rs:79:21
    |
 LL |     const IF: i32 = if true { 5 } else { 6 };
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -220,7 +220,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `if` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:81:25
+  --> $DIR/feature-gate-const-if-match.rs:82:25
    |
 LL |     const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -229,7 +229,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0658]: `match` is not allowed in a `const`
-  --> $DIR/feature-gate-const-if-match.rs:84:24
+  --> $DIR/feature-gate-const-if-match.rs:85:24
    |
 LL |     const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -238,7 +238,7 @@
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/feature-gate-const-if-match.rs:114:21
+  --> $DIR/feature-gate-const-if-match.rs:115:21
    |
 LL |         if let Some(x) = Some(x) { x } else { 1 }
    |                     ^
diff --git a/src/test/ui/consts/control-flow/short-circuit-let.rs b/src/test/ui/consts/control-flow/short-circuit-let.rs
index 8cee2a5..4b20a21 100644
--- a/src/test/ui/consts/control-flow/short-circuit-let.rs
+++ b/src/test/ui/consts/control-flow/short-circuit-let.rs
@@ -4,6 +4,7 @@
 
 #![feature(const_if_match)]
 #![feature(const_panic)]
+#![feature(const_fn)]
 
 const X: i32 = {
     let mut x = 0;
diff --git a/src/test/ui/consts/control-flow/single_variant_match_ice.rs b/src/test/ui/consts/control-flow/single_variant_match_ice.rs
index 823605f..bb0fce6 100644
--- a/src/test/ui/consts/control-flow/single_variant_match_ice.rs
+++ b/src/test/ui/consts/control-flow/single_variant_match_ice.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(const_if_match)]
+#![feature(const_if_match, const_fn)]
 
 enum Foo {
     Prob,
diff --git a/src/test/ui/consts/issue-64662.stderr b/src/test/ui/consts/issue-64662.stderr
index b81daae..b3c673e 100644
--- a/src/test/ui/consts/issue-64662.stderr
+++ b/src/test/ui/consts/issue-64662.stderr
@@ -2,13 +2,13 @@
   --> $DIR/issue-64662.rs:2:9
    |
 LL |     A = foo(),
-   |         ^^^ cannot infer type for `T`
+   |         ^^^ cannot infer type for type parameter `T`
 
 error[E0282]: type annotations needed
   --> $DIR/issue-64662.rs:3:9
    |
 LL |     B = foo(),
-   |         ^^^ cannot infer type for `T`
+   |         ^^^ cannot infer type for type parameter `T`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs
index 44b4084..972f595 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_const.rs
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.rs
@@ -1,6 +1,7 @@
 // compile-flags: -Zunleash-the-miri-inside-of-you
 
 #![feature(const_raw_ptr_deref)]
+#![feature(const_mut_refs)]
 #![deny(const_err)]
 
 use std::cell::UnsafeCell;
@@ -12,9 +13,7 @@
 const MUTATING_BEHIND_RAW: () = {
     // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
     unsafe {
-        *MUTABLE_BEHIND_RAW = 99 //~ WARN skipping const checks
-        //~^ ERROR any use of this value will cause an error
-        //~^^ tried to modify constant memory
+        *MUTABLE_BEHIND_RAW = 99 //~ ERROR any use of this value will cause an error
     }
 };
 
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
index 757f0ff..9daca76 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
@@ -1,30 +1,23 @@
 warning: skipping const checks
-  --> $DIR/mutable_const.rs:9:38
+  --> $DIR/mutable_const.rs:10:38
    |
 LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
    |                                      ^^^^^^^^^^^^^^^^^^^^
 
-warning: skipping const checks
-  --> $DIR/mutable_const.rs:15:9
-   |
-LL |         *MUTABLE_BEHIND_RAW = 99
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: any use of this value will cause an error
-  --> $DIR/mutable_const.rs:15:9
+  --> $DIR/mutable_const.rs:16:9
    |
 LL | / const MUTATING_BEHIND_RAW: () = {
 LL | |     // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
 LL | |     unsafe {
 LL | |         *MUTABLE_BEHIND_RAW = 99
    | |         ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory
-...  |
 LL | |     }
 LL | | };
    | |__-
    |
 note: lint level defined here
-  --> $DIR/mutable_const.rs:4:9
+  --> $DIR/mutable_const.rs:5:9
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.rs b/src/test/ui/consts/miri_unleashed/mutable_references.rs
index 59dafcb..fe3c4ee 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references.rs
+++ b/src/test/ui/consts/miri_unleashed/mutable_references.rs
@@ -1,20 +1,22 @@
 // compile-flags: -Zunleash-the-miri-inside-of-you
+#![feature(const_mut_refs)]
 #![allow(const_err)]
 
 use std::cell::UnsafeCell;
 
 // a test demonstrating what things we could allow with a smarter const qualification
 
+// this is fine because is not possible to mutate through an immutable reference.
 static FOO: &&mut u32 = &&mut 42;
-//~^ WARN: skipping const checks
 
+// this is fine because accessing an immutable static `BAR` is equivalent to accessing `*&BAR`
+// which puts the mutable reference behind an immutable one.
 static BAR: &mut () = &mut ();
-//~^ WARN: skipping const checks
 
 struct Foo<T>(T);
 
+// this is fine for the same reason as `BAR`.
 static BOO: &mut Foo<()> = &mut Foo(());
-//~^ WARN: skipping const checks
 
 struct Meh {
     x: &'static UnsafeCell<i32>,
@@ -27,8 +29,8 @@
     //~^ WARN: skipping const checks
 };
 
+// this is fine for the same reason as `BAR`.
 static OH_YES: &mut i32 = &mut 42;
-//~^ WARN: skipping const checks
 
 fn main() {
     unsafe {
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.stderr b/src/test/ui/consts/miri_unleashed/mutable_references.stderr
index b9c0af3..3e1300c 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references.stderr
@@ -1,35 +1,11 @@
 warning: skipping const checks
-  --> $DIR/mutable_references.rs:8:26
-   |
-LL | static FOO: &&mut u32 = &&mut 42;
-   |                          ^^^^^^^
-
-warning: skipping const checks
-  --> $DIR/mutable_references.rs:11:23
-   |
-LL | static BAR: &mut () = &mut ();
-   |                       ^^^^^^^
-
-warning: skipping const checks
-  --> $DIR/mutable_references.rs:16:28
-   |
-LL | static BOO: &mut Foo<()> = &mut Foo(());
-   |                            ^^^^^^^^^^^^
-
-warning: skipping const checks
-  --> $DIR/mutable_references.rs:26:8
+  --> $DIR/mutable_references.rs:28:8
    |
 LL |     x: &UnsafeCell::new(42),
    |        ^^^^^^^^^^^^^^^^^^^^
 
-warning: skipping const checks
-  --> $DIR/mutable_references.rs:30:27
-   |
-LL | static OH_YES: &mut i32 = &mut 42;
-   |                           ^^^^^^^
-
 error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item
-  --> $DIR/mutable_references.rs:37:5
+  --> $DIR/mutable_references.rs:39:5
    |
 LL |     *OH_YES = 99;
    |     ^^^^^^^^^^^^ cannot assign
diff --git a/src/test/ui/consts/miri_unleashed/read_from_static.rs b/src/test/ui/consts/miri_unleashed/read_from_static.rs
new file mode 100644
index 0000000..821c501
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/read_from_static.rs
@@ -0,0 +1,11 @@
+// run-pass
+// compile-flags: -Zunleash-the-miri-inside-of-you
+#![feature(const_mut_refs)]
+#![allow(const_err)]
+
+static OH_YES: &mut i32 = &mut 42;
+
+fn main() {
+    // Make sure `OH_YES` can be read.
+    assert_eq!(*OH_YES, 42);
+}
diff --git a/src/test/ui/consts/projection_qualif.mut_refs.stderr b/src/test/ui/consts/projection_qualif.mut_refs.stderr
new file mode 100644
index 0000000..2353877
--- /dev/null
+++ b/src/test/ui/consts/projection_qualif.mut_refs.stderr
@@ -0,0 +1,12 @@
+error[E0658]: dereferencing raw pointers in constants is unstable
+  --> $DIR/projection_qualif.rs:11:18
+   |
+LL |         unsafe { *b = 5; }
+   |                  ^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
+   = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs
index dedb7db..cfe8e7f 100644
--- a/src/test/ui/consts/projection_qualif.rs
+++ b/src/test/ui/consts/projection_qualif.rs
@@ -1,11 +1,15 @@
+// revisions: stock mut_refs
+
+#![cfg_attr(mut_refs, feature(const_mut_refs))]
+
 use std::cell::Cell;
 
 const FOO: &u32 = {
     let mut a = 42;
     {
-        let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
+        let b: *mut u32 = &mut a; //[stock]~ ERROR may only refer to immutable values
         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
-        //~^ contains unimplemented expression
+        //[stock]~^ contains unimplemented expression
     }
     &{a}
 };
diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr
deleted file mode 100644
index 0efb6bf..0000000
--- a/src/test/ui/consts/projection_qualif.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0017]: references in constants may only refer to immutable values
-  --> $DIR/projection_qualif.rs:6:27
-   |
-LL |         let b: *mut u32 = &mut a;
-   |                           ^^^^^^ constants require immutable values
-
-error[E0658]: dereferencing raw pointers in constants is unstable
-  --> $DIR/projection_qualif.rs:7:18
-   |
-LL |         unsafe { *b = 5; }
-   |                  ^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
-   = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
-
-error[E0019]: constant contains unimplemented expression type
-  --> $DIR/projection_qualif.rs:7:18
-   |
-LL |         unsafe { *b = 5; }
-   |                  ^^^^^^
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0017, E0019, E0658.
-For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/projection_qualif.stock.stderr b/src/test/ui/consts/projection_qualif.stock.stderr
new file mode 100644
index 0000000..472d260
--- /dev/null
+++ b/src/test/ui/consts/projection_qualif.stock.stderr
@@ -0,0 +1,28 @@
+error[E0658]: references in constants may only refer to immutable values
+  --> $DIR/projection_qualif.rs:10:27
+   |
+LL |         let b: *mut u32 = &mut a;
+   |                           ^^^^^^ constants require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: dereferencing raw pointers in constants is unstable
+  --> $DIR/projection_qualif.rs:11:18
+   |
+LL |         unsafe { *b = 5; }
+   |                  ^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
+   = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/projection_qualif.rs:11:18
+   |
+LL |         unsafe { *b = 5; }
+   |                  ^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
new file mode 100644
index 0000000..b43fbc8
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
@@ -0,0 +1,9 @@
+error[E0080]: could not evaluate static initializer
+  --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+   |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
index ef378fa..74162fb 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
@@ -1,7 +1,12 @@
+// revisions: stock mut_refs
+
+#![cfg_attr(mut_refs, feature(const_mut_refs))]
+
 static mut STDERR_BUFFER_SPACE: u8 = 0;
 
 pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-//~^ ERROR references in statics may only refer to immutable values
-//~| ERROR static contains unimplemented expression type
+//[mut_refs]~^ ERROR could not evaluate static initializer
+//[stock]~^^ ERROR references in statics may only refer to immutable values
+//[stock]~| ERROR static contains unimplemented expression type
 
 fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
deleted file mode 100644
index ca691b0..0000000
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0017]: references in statics may only refer to immutable values
-  --> $DIR/static_mut_containing_mut_ref2.rs:3:46
-   |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
-
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/static_mut_containing_mut_ref2.rs:3:45
-   |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0017, E0019.
-For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
new file mode 100644
index 0000000..430cef9
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
@@ -0,0 +1,19 @@
+error[E0658]: references in statics may only refer to immutable values
+  --> $DIR/static_mut_containing_mut_ref2.rs:7:46
+   |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+   |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.rs b/src/test/ui/consts/unstable-const-fn-in-libcore.rs
new file mode 100644
index 0000000..cad1516
--- /dev/null
+++ b/src/test/ui/consts/unstable-const-fn-in-libcore.rs
@@ -0,0 +1,29 @@
+// This is a non-regression test for const-qualification of unstable items in libcore
+// as explained in issue #67053.
+// const-qualification could miss some `const fn`s if they were unstable and the feature
+// gate was not enabled in libcore.
+
+#![stable(feature = "core", since = "1.6.0")]
+#![feature(const_if_match)]
+#![feature(rustc_const_unstable)]
+#![feature(staged_api)]
+
+enum Opt<T> {
+    Some(T),
+    None,
+}
+
+impl<T> Opt<T> {
+    #[rustc_const_unstable(feature = "foo")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
+    //~^ ERROR destructors cannot be evaluated at compile-time
+    //~| ERROR destructors cannot be evaluated at compile-time
+        match self {
+            Opt::Some(t) => t,
+            Opt::None => f(), //~ ERROR E0015
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr
new file mode 100644
index 0000000..a8455ce
--- /dev/null
+++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr
@@ -0,0 +1,22 @@
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/unstable-const-fn-in-libcore.rs:24:26
+   |
+LL |             Opt::None => f(),
+   |                          ^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/unstable-const-fn-in-libcore.rs:19:53
+   |
+LL |     const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
+   |                                                     ^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/unstable-const-fn-in-libcore.rs:19:47
+   |
+LL |     const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
+   |                                               ^^^^ constant functions cannot evaluate destructors
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0015, E0493.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs
index 29dcbfe..0f0ec0b 100644
--- a/src/test/ui/drop/dynamic-drop.rs
+++ b/src/test/ui/drop/dynamic-drop.rs
@@ -269,6 +269,28 @@
     let[_, _y @ ..] = ar;
 }
 
+fn index_field_mixed_ends(a: &Allocator) {
+    let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())];
+    let[(_x, _), ..] = ar;
+    let[(_, _y), _] = ar;
+    let[_, (_, _w)] = ar;
+    let[.., (_z, _)] = ar;
+}
+
+fn subslice_mixed_min_lengths(a: &Allocator, c: i32) {
+    let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())];
+    match c {
+        0 => { let[_x, ..] = ar; }
+        1 => { let[_x, _, ..] = ar; }
+        2 => { let[_x, _] = ar; }
+        3 => { let[(_x, _), _, ..] = ar; }
+        4 => { let[.., (_x, _)] = ar; }
+        5 => { let[.., (_x, _), _] = ar; }
+        6 => { let [_y @ ..] = ar; }
+        _ => { let [_y @ .., _] = ar; }
+    }
+}
+
 fn panic_after_return(a: &Allocator) -> Ptr<'_> {
     // Panic in the drop of `p` or `q` can leak
     let exceptions = vec![8, 9];
@@ -422,6 +444,16 @@
     run_test(|a| slice_pattern_reassign(a));
     run_test(|a| subslice_pattern_reassign(a));
 
+    run_test(|a| index_field_mixed_ends(a));
+    run_test(|a| subslice_mixed_min_lengths(a, 0));
+    run_test(|a| subslice_mixed_min_lengths(a, 1));
+    run_test(|a| subslice_mixed_min_lengths(a, 2));
+    run_test(|a| subslice_mixed_min_lengths(a, 3));
+    run_test(|a| subslice_mixed_min_lengths(a, 4));
+    run_test(|a| subslice_mixed_min_lengths(a, 5));
+    run_test(|a| subslice_mixed_min_lengths(a, 6));
+    run_test(|a| subslice_mixed_min_lengths(a, 7));
+
     run_test(|a| {
         panic_after_return(a);
     });
diff --git a/src/test/ui/enum/union-in-enum.rs b/src/test/ui/enum/union-in-enum.rs
new file mode 100644
index 0000000..048913e
--- /dev/null
+++ b/src/test/ui/enum/union-in-enum.rs
@@ -0,0 +1,13 @@
+// This test checks that the union keyword
+// is accepted as the name of an enum variant
+// when not followed by an identifier
+// This special case exists because `union` is a contextual keyword.
+
+#![allow(warnings)]
+
+// check-pass
+
+enum A { union }
+enum B { union {} }
+enum C { union() }
+fn main(){}
diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr
index db0a2b5..f5b41cd 100644
--- a/src/test/ui/error-codes/E0004-2.stderr
+++ b/src/test/ui/error-codes/E0004-2.stderr
@@ -1,8 +1,8 @@
-error[E0004]: non-exhaustive patterns: multiple patterns of type `std::option::Option<i32>` are not handled
+error[E0004]: non-exhaustive patterns: `None` and `Some(_)` not covered
   --> $DIR/E0004-2.rs:4:11
    |
 LL |     match x { }
-   |           ^
+   |           ^ patterns `None` and `Some(_)` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs
index 3bc518c..64be411 100644
--- a/src/test/ui/error-codes/E0017.rs
+++ b/src/test/ui/error-codes/E0017.rs
@@ -2,10 +2,10 @@
 const C: i32 = 2;
 static mut M: i32 = 3;
 
-const CR: &'static mut i32 = &mut C; //~ ERROR E0017
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+const CR: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
                                               //~| ERROR E0019
                                               //~| ERROR cannot borrow
-static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
-static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0017
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0658
 fn main() {}
diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr
index 8c8660a..9a87195 100644
--- a/src/test/ui/error-codes/E0017.stderr
+++ b/src/test/ui/error-codes/E0017.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
   --> $DIR/E0017.rs:5:30
    |
 LL | const CR: &'static mut i32 = &mut C;
    |                              ^^^^^^ constants require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0019]: static contains unimplemented expression type
   --> $DIR/E0017.rs:6:39
@@ -10,11 +13,14 @@
 LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^
 
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
   --> $DIR/E0017.rs:6:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^ statics require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0596]: cannot borrow immutable static item `X` as mutable
   --> $DIR/E0017.rs:6:39
@@ -22,19 +28,25 @@
 LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^ cannot borrow as mutable
 
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
   --> $DIR/E0017.rs:9:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
    |                                      ^^^^^^ statics require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
   --> $DIR/E0017.rs:10:52
    |
 LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
    |                                                    ^^^^^^ statics require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0017, E0019, E0596.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0019, E0596, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr
index aba649d..ae5b7c3 100644
--- a/src/test/ui/error-codes/E0283.stderr
+++ b/src/test/ui/error-codes/E0283.stderr
@@ -1,11 +1,13 @@
-error[E0283]: type annotations needed: cannot resolve `_: Generator`
+error[E0283]: type annotations needed
   --> $DIR/E0283.rs:18:21
    |
 LL |     fn create() -> u32;
    |     ------------------- required by `Generator::create`
 ...
 LL |     let cont: u32 = Generator::create();
-   |                     ^^^^^^^^^^^^^^^^^
+   |                     ^^^^^^^^^^^^^^^^^ cannot infer type
+   |
+   = note: cannot resolve `_: Generator`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs
new file mode 100644
index 0000000..5954e34
--- /dev/null
+++ b/src/test/ui/error-codes/E0388.rs
@@ -0,0 +1,10 @@
+static X: i32 = 1;
+const C: i32 = 2;
+
+const CR: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
+                                              //~| ERROR cannot borrow
+                                              //~| ERROR E0019
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr
new file mode 100644
index 0000000..986307d
--- /dev/null
+++ b/src/test/ui/error-codes/E0388.stderr
@@ -0,0 +1,43 @@
+error[E0658]: references in constants may only refer to immutable values
+  --> $DIR/E0388.rs:4:30
+   |
+LL | const CR: &'static mut i32 = &mut C;
+   |                              ^^^^^^ constants require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/E0388.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^
+
+error[E0658]: references in statics may only refer to immutable values
+  --> $DIR/E0388.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^ statics require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0596]: cannot borrow immutable static item `X` as mutable
+  --> $DIR/E0388.rs:5:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+   |                                       ^^^^^^ cannot borrow as mutable
+
+error[E0658]: references in statics may only refer to immutable values
+  --> $DIR/E0388.rs:8:38
+   |
+LL | static CONST_REF: &'static mut i32 = &mut C;
+   |                                      ^^^^^^ statics require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0019, E0596, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr
index 485b76a..0adf982 100644
--- a/src/test/ui/error-codes/E0401.stderr
+++ b/src/test/ui/error-codes/E0401.stderr
@@ -36,7 +36,7 @@
   --> $DIR/E0401.rs:11:5
    |
 LL |     bfnr(x);
-   |     ^^^^ cannot infer type for `U`
+   |     ^^^^ cannot infer type for type parameter `U`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/extern-flag/auxiliary/somedep.rs b/src/test/ui/extern-flag/auxiliary/somedep.rs
new file mode 100644
index 0000000..dd2f373
--- /dev/null
+++ b/src/test/ui/extern-flag/auxiliary/somedep.rs
@@ -0,0 +1,3 @@
+pub fn somefun() {}
+
+pub struct S;
diff --git a/src/test/ui/extern-flag/multiple-opts.rs b/src/test/ui/extern-flag/multiple-opts.rs
new file mode 100644
index 0000000..3dc2f1d
--- /dev/null
+++ b/src/test/ui/extern-flag/multiple-opts.rs
@@ -0,0 +1,20 @@
+// aux-crate:priv,noprelude:somedep=somedep.rs
+// compile-flags: -Zunstable-options
+// edition:2018
+
+// Test for multiple options to --extern. Can't test for errors from both
+// options at the same time, so this only checks that noprelude is honored.
+
+#![warn(exported_private_dependencies)]
+
+// Module to avoid adding to prelude.
+pub mod m {
+    extern crate somedep;
+    pub struct PublicType {
+        pub field: somedep::S,
+    }
+}
+
+fn main() {
+    somedep::somefun();  //~ ERROR failed to resolve
+}
diff --git a/src/test/ui/extern-flag/multiple-opts.stderr b/src/test/ui/extern-flag/multiple-opts.stderr
new file mode 100644
index 0000000..3bf73d1
--- /dev/null
+++ b/src/test/ui/extern-flag/multiple-opts.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `somedep`
+  --> $DIR/multiple-opts.rs:19:5
+   |
+LL |     somedep::somefun();
+   |     ^^^^^^^ use of undeclared type or module `somedep`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/extern-flag/noprelude-and-prelude.rs b/src/test/ui/extern-flag/noprelude-and-prelude.rs
new file mode 100644
index 0000000..e6a150b
--- /dev/null
+++ b/src/test/ui/extern-flag/noprelude-and-prelude.rs
@@ -0,0 +1,10 @@
+// check-pass
+// aux-crate:noprelude:somedep=somedep.rs
+// compile-flags: -Zunstable-options --extern somedep
+// edition:2018
+
+// Having a flag with `noprelude` and one without, will add to the prelude.
+
+fn main() {
+    somedep::somefun();
+}
diff --git a/src/test/ui/extern-flag/noprelude-resolves.rs b/src/test/ui/extern-flag/noprelude-resolves.rs
new file mode 100644
index 0000000..f69f552
--- /dev/null
+++ b/src/test/ui/extern-flag/noprelude-resolves.rs
@@ -0,0 +1,11 @@
+// check-pass
+// aux-crate:noprelude:somedep=somedep.rs
+// compile-flags: -Zunstable-options
+// edition:2018
+
+// `extern crate` can be used to add to prelude.
+extern crate somedep;
+
+fn main() {
+    somedep::somefun();
+}
diff --git a/src/test/ui/extern-flag/noprelude.rs b/src/test/ui/extern-flag/noprelude.rs
new file mode 100644
index 0000000..cdbf340
--- /dev/null
+++ b/src/test/ui/extern-flag/noprelude.rs
@@ -0,0 +1,7 @@
+// aux-crate:noprelude:somedep=somedep.rs
+// compile-flags: -Zunstable-options
+// edition:2018
+
+fn main() {
+    somedep::somefun();  //~ ERROR failed to resolve
+}
diff --git a/src/test/ui/extern-flag/noprelude.stderr b/src/test/ui/extern-flag/noprelude.stderr
new file mode 100644
index 0000000..beb9200
--- /dev/null
+++ b/src/test/ui/extern-flag/noprelude.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type or module `somedep`
+  --> $DIR/noprelude.rs:6:5
+   |
+LL |     somedep::somefun();
+   |     ^^^^^^^ use of undeclared type or module `somedep`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/extern-flag/public-and-private.rs b/src/test/ui/extern-flag/public-and-private.rs
new file mode 100644
index 0000000..a3a81cb
--- /dev/null
+++ b/src/test/ui/extern-flag/public-and-private.rs
@@ -0,0 +1,13 @@
+// aux-crate:priv:somedep=somedep.rs
+// compile-flags: -Zunstable-options --extern somedep
+// edition:2018
+
+#![deny(exported_private_dependencies)]
+
+// Having a flag with `priv` and one without, will remain private (it is sticky).
+
+pub struct PublicType {
+    pub field: somedep::S, //~ ERROR from private dependency
+}
+
+fn main() {}
diff --git a/src/test/ui/extern-flag/public-and-private.stderr b/src/test/ui/extern-flag/public-and-private.stderr
new file mode 100644
index 0000000..72f1bb2
--- /dev/null
+++ b/src/test/ui/extern-flag/public-and-private.stderr
@@ -0,0 +1,14 @@
+error: type `somedep::S` from private dependency 'somedep' in public interface
+  --> $DIR/public-and-private.rs:10:5
+   |
+LL |     pub field: somedep::S,
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/public-and-private.rs:5:9
+   |
+LL | #![deny(exported_private_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/for-loop-while/label_break_value.rs b/src/test/ui/for-loop-while/label_break_value.rs
index eb5be77..18930ac 100644
--- a/src/test/ui/for-loop-while/label_break_value.rs
+++ b/src/test/ui/for-loop-while/label_break_value.rs
@@ -77,7 +77,7 @@
         }
         // Labeled breaking an outer loop still works
         'd: loop {
-            'e: {
+            {
                 if v == r {
                     break 'b;
                 }
diff --git a/src/test/ui/for-loop-while/loop-label-shadowing.rs b/src/test/ui/for-loop-while/loop-label-shadowing.rs
index acb53e2..9bedde6 100644
--- a/src/test/ui/for-loop-while/loop-label-shadowing.rs
+++ b/src/test/ui/for-loop-while/loop-label-shadowing.rs
@@ -5,6 +5,7 @@
 
 fn main() {
     let mut foo = Vec::new();
+    #[allow(unused_labels)]
     'foo: for i in &[1, 2, 3] {
         foo.push(*i);
     }
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
index b388f38..ca61fb0 100644
--- a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
@@ -4,7 +4,10 @@
 LL | fn bar(x: usize) -> Option<usize> {
    |                     ------------- expected `std::option::Option<usize>` because of return type
 LL |     return x;
-   |            ^ expected enum `std::option::Option`, found `usize`
+   |            ^
+   |            |
+   |            expected enum `std::option::Option`, found `usize`
+   |            help: try using a variant of the expected enum: `Some(x)`
    |
    = note: expected enum `std::option::Option<usize>`
               found type `usize`
diff --git a/src/test/ui/generator/not-send-sync.rs b/src/test/ui/generator/not-send-sync.rs
index ae0a288..0db01c6 100644
--- a/src/test/ui/generator/not-send-sync.rs
+++ b/src/test/ui/generator/not-send-sync.rs
@@ -7,7 +7,7 @@
     fn assert_send<T: Send>(_: T) {}
 
     assert_sync(|| {
-        //~^ ERROR: E0277
+        //~^ ERROR: future cannot be shared between threads safely
         let a = Cell::new(2);
         yield;
     });
diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr
index 620db24..0ac1d18 100644
--- a/src/test/ui/generator/not-send-sync.stderr
+++ b/src/test/ui/generator/not-send-sync.stderr
@@ -11,18 +11,25 @@
    = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell<i32>`
    = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell<i32> _]`
 
-error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
+error: future cannot be shared between threads safely
   --> $DIR/not-send-sync.rs:9:5
    |
 LL |     fn assert_sync<T: Sync>(_: T) {}
    |        -----------    ---- required by this bound in `main::assert_sync`
 ...
 LL |     assert_sync(|| {
-   |     ^^^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
+   |     ^^^^^^^^^^^ future returned by `main` is not `Sync`
    |
    = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
-   = note: required because it appears within the type `{std::cell::Cell<i32>, ()}`
-   = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`
+note: future is not `Sync` as this value is used across an yield
+  --> $DIR/not-send-sync.rs:12:9
+   |
+LL |         let a = Cell::new(2);
+   |             - has type `std::cell::Cell<i32>`
+LL |         yield;
+   |         ^^^^^ yield occurs here, with `a` maybe used later
+LL |     });
+   |     - `a` is later dropped here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.polonius.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.polonius.stderr
new file mode 100644
index 0000000..558d643
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.polonius.stderr
@@ -0,0 +1,68 @@
+warning: function cannot return without recursing
+  --> $DIR/hrtb-perfect-forwarding.rs:22:1
+   |
+LL | / fn no_hrtb<'b,T>(mut t: T)
+LL | |     where T : Bar<&'b isize>
+LL | | {
+LL | |     // OK -- `T : Bar<&'b isize>`, and thus the impl above ensures that
+LL | |     // `&mut T : Bar<&'b isize>`.
+LL | |     no_hrtb(&mut t);
+   | |     --------------- recursive call site
+LL | | }
+   | |_^ cannot return without recursing
+   |
+   = note: `#[warn(unconditional_recursion)]` on by default
+   = help: a `loop` may express intention better if this is on purpose
+
+warning: function cannot return without recursing
+  --> $DIR/hrtb-perfect-forwarding.rs:30:1
+   |
+LL | / fn bar_hrtb<T>(mut t: T)
+LL | |     where T : for<'b> Bar<&'b isize>
+LL | | {
+LL | |     // OK -- `T : for<'b> Bar<&'b isize>`, and thus the impl above
+...  |
+LL | |     bar_hrtb(&mut t);
+   | |     ---------------- recursive call site
+LL | | }
+   | |_^ cannot return without recursing
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+warning: function cannot return without recursing
+  --> $DIR/hrtb-perfect-forwarding.rs:39:1
+   |
+LL | / fn foo_hrtb_bar_not<'b,T>(mut t: T)
+LL | |     where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
+LL | | {
+LL | |     // Not OK -- The forwarding impl for `Foo` requires that `Bar` also
+...  |
+LL | |     foo_hrtb_bar_not(&mut t);
+   | |     ------------------------ recursive call site
+LL | | }
+   | |_^ cannot return without recursing
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: higher-ranked subtype error
+  --> $DIR/hrtb-perfect-forwarding.rs:46:5
+   |
+LL |     foo_hrtb_bar_not(&mut t);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: function cannot return without recursing
+  --> $DIR/hrtb-perfect-forwarding.rs:49:1
+   |
+LL | / fn foo_hrtb_bar_hrtb<T>(mut t: T)
+LL | |     where T : for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>
+LL | | {
+LL | |     // OK -- now we have `T : for<'b> Bar&'b isize>`.
+LL | |     foo_hrtb_bar_hrtb(&mut t);
+   | |     ------------------------- recursive call site
+LL | | }
+   | |_^ cannot return without recursing
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hygiene/hygienic-labels-in-let.rs b/src/test/ui/hygiene/hygienic-labels-in-let.rs
index 5d22cf8..491855d 100644
--- a/src/test/ui/hygiene/hygienic-labels-in-let.rs
+++ b/src/test/ui/hygiene/hygienic-labels-in-let.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(unreachable_code)]
+#![allow(unused_labels)]
 
 // Test that labels injected by macros do not break hygiene.  This
 // checks cases where the macros invocations are under the rhs of a
diff --git a/src/test/ui/hygiene/hygienic-labels-in-let.stderr b/src/test/ui/hygiene/hygienic-labels-in-let.stderr
index d88470f..4acb34f 100644
--- a/src/test/ui/hygiene/hygienic-labels-in-let.stderr
+++ b/src/test/ui/hygiene/hygienic-labels-in-let.stderr
@@ -1,5 +1,5 @@
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:15:9
+  --> $DIR/hygienic-labels-in-let.rs:16:9
    |
 LL |         'x: loop { $e }
    |         ^^ lifetime 'x already in scope
@@ -11,7 +11,7 @@
    |             ------------------ in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:63:9
+  --> $DIR/hygienic-labels-in-let.rs:64:9
    |
 LL |         'x: loop {
    |         -- first declared here
@@ -20,7 +20,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:63:9
+  --> $DIR/hygienic-labels-in-let.rs:64:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -29,7 +29,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:15:9
+  --> $DIR/hygienic-labels-in-let.rs:16:9
    |
 LL |         'x: loop { $e }
    |         ^^ lifetime 'x already in scope
@@ -41,7 +41,7 @@
    |             ------------------ in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:15:9
+  --> $DIR/hygienic-labels-in-let.rs:16:9
    |
 LL |         'x: loop { $e }
    |         ^^
@@ -53,7 +53,7 @@
    |             ------------------ in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:15:9
+  --> $DIR/hygienic-labels-in-let.rs:16:9
    |
 LL |         'x: loop { $e }
    |         ^^ lifetime 'x already in scope
@@ -65,7 +65,7 @@
    |             ------------------ in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:75:9
+  --> $DIR/hygienic-labels-in-let.rs:76:9
    |
 LL |         'x: loop {
    |         -- first declared here
@@ -74,7 +74,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:75:9
+  --> $DIR/hygienic-labels-in-let.rs:76:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -83,7 +83,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:75:9
+  --> $DIR/hygienic-labels-in-let.rs:76:9
    |
 LL |         'x: for _ in 0..1 {
    |         -- first declared here
@@ -92,7 +92,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:75:9
+  --> $DIR/hygienic-labels-in-let.rs:76:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -101,7 +101,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:26:9
+  --> $DIR/hygienic-labels-in-let.rs:27:9
    |
 LL |         'x: while 1 + 1 == 2 { $e }
    |         ^^ lifetime 'x already in scope
@@ -113,7 +113,7 @@
    |             ---------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:26:9
+  --> $DIR/hygienic-labels-in-let.rs:27:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -125,7 +125,7 @@
    |             ---------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:26:9
+  --> $DIR/hygienic-labels-in-let.rs:27:9
    |
 LL |         'x: while 1 + 1 == 2 { $e }
    |         ^^ lifetime 'x already in scope
@@ -137,7 +137,7 @@
    |             ---------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:26:9
+  --> $DIR/hygienic-labels-in-let.rs:27:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -149,7 +149,7 @@
    |             ---------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:26:9
+  --> $DIR/hygienic-labels-in-let.rs:27:9
    |
 LL |         'x: while 1 + 1 == 2 { $e }
    |         ^^ lifetime 'x already in scope
@@ -161,7 +161,7 @@
    |             ---------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:89:9
+  --> $DIR/hygienic-labels-in-let.rs:90:9
    |
 LL |         'x: loop {
    |         -- first declared here
@@ -170,7 +170,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:89:9
+  --> $DIR/hygienic-labels-in-let.rs:90:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -179,7 +179,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:89:9
+  --> $DIR/hygienic-labels-in-let.rs:90:9
    |
 LL |         'x: for _ in 0..1 {
    |         -- first declared here
@@ -188,7 +188,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:89:9
+  --> $DIR/hygienic-labels-in-let.rs:90:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -197,7 +197,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:89:9
+  --> $DIR/hygienic-labels-in-let.rs:90:9
    |
 LL |         'x: for _ in 0..1 {
    |         -- first declared here
@@ -206,7 +206,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:89:9
+  --> $DIR/hygienic-labels-in-let.rs:90:9
    |
 LL |         'x: while 1 + 1 == 2 { $e }
    |         -- first declared here
@@ -215,7 +215,7 @@
    |         ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:38:9
+  --> $DIR/hygienic-labels-in-let.rs:39:9
    |
 LL |         'x: for _ in 0..1 { $e }
    |         ^^ lifetime 'x already in scope
@@ -227,7 +227,7 @@
    |             ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:38:9
+  --> $DIR/hygienic-labels-in-let.rs:39:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -239,7 +239,7 @@
    |             ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:38:9
+  --> $DIR/hygienic-labels-in-let.rs:39:9
    |
 LL |         'x: for _ in 0..1 { $e }
    |         ^^ lifetime 'x already in scope
@@ -251,7 +251,7 @@
    |             ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:38:9
+  --> $DIR/hygienic-labels-in-let.rs:39:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -263,7 +263,7 @@
    |             ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:38:9
+  --> $DIR/hygienic-labels-in-let.rs:39:9
    |
 LL |         'x: for _ in 0..1 { $e }
    |         ^^ lifetime 'x already in scope
@@ -275,7 +275,7 @@
    |             ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:38:9
+  --> $DIR/hygienic-labels-in-let.rs:39:9
    |
 LL |         'x: while 1 + 1 == 2 { $e }
    |         -- first declared here
@@ -287,7 +287,7 @@
    |             ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels-in-let.rs:38:9
+  --> $DIR/hygienic-labels-in-let.rs:39:9
    |
 LL |         'x: for _ in 0..1 { $e }
    |         ^^ lifetime 'x already in scope
diff --git a/src/test/ui/hygiene/hygienic-labels.rs b/src/test/ui/hygiene/hygienic-labels.rs
index 8eafb4c..c9f494b 100644
--- a/src/test/ui/hygiene/hygienic-labels.rs
+++ b/src/test/ui/hygiene/hygienic-labels.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(unreachable_code)]
+#![allow(unused_labels)]
 // Test that labels injected by macros do not break hygiene.
 
 // Issue #24278: The label/lifetime shadowing checker from #24162
diff --git a/src/test/ui/hygiene/hygienic-labels.stderr b/src/test/ui/hygiene/hygienic-labels.stderr
index 285e903..0833825 100644
--- a/src/test/ui/hygiene/hygienic-labels.stderr
+++ b/src/test/ui/hygiene/hygienic-labels.stderr
@@ -1,5 +1,5 @@
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:12:9
+  --> $DIR/hygienic-labels.rs:13:9
    |
 LL |         'x: loop { $e }
    |         ^^ lifetime 'x already in scope
@@ -11,7 +11,7 @@
    |         ------------------ in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:53:5
+  --> $DIR/hygienic-labels.rs:54:5
    |
 LL |     'x: for _ in 0..1 {
    |     -- first declared here
@@ -20,7 +20,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:53:5
+  --> $DIR/hygienic-labels.rs:54:5
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -29,7 +29,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:12:9
+  --> $DIR/hygienic-labels.rs:13:9
    |
 LL |         'x: loop { $e }
    |         ^^ lifetime 'x already in scope
@@ -41,7 +41,7 @@
    |         ------------------ in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:12:9
+  --> $DIR/hygienic-labels.rs:13:9
    |
 LL |         'x: loop { $e }
    |         ^^
@@ -53,7 +53,7 @@
    |         ------------------ in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:12:9
+  --> $DIR/hygienic-labels.rs:13:9
    |
 LL |         'x: loop { $e }
    |         ^^ lifetime 'x already in scope
@@ -65,7 +65,7 @@
    |         ------------------ in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:62:5
+  --> $DIR/hygienic-labels.rs:63:5
    |
 LL |     'x: for _ in 0..1 {
    |     -- first declared here
@@ -74,7 +74,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:62:5
+  --> $DIR/hygienic-labels.rs:63:5
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -83,7 +83,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:62:5
+  --> $DIR/hygienic-labels.rs:63:5
    |
 LL |     'x: loop {
    |     -- first declared here
@@ -92,7 +92,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:62:5
+  --> $DIR/hygienic-labels.rs:63:5
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -101,7 +101,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:37:9
+  --> $DIR/hygienic-labels.rs:38:9
    |
 LL |         'x: while 1 + 1 == 2 { $e }
    |         ^^ lifetime 'x already in scope
@@ -113,7 +113,7 @@
    |         ------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:37:9
+  --> $DIR/hygienic-labels.rs:38:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -125,7 +125,7 @@
    |         ------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:37:9
+  --> $DIR/hygienic-labels.rs:38:9
    |
 LL |         'x: while 1 + 1 == 2 { $e }
    |         ^^ lifetime 'x already in scope
@@ -137,7 +137,7 @@
    |         ------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:37:9
+  --> $DIR/hygienic-labels.rs:38:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -149,7 +149,7 @@
    |         ------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:37:9
+  --> $DIR/hygienic-labels.rs:38:9
    |
 LL |         'x: while 1 + 1 == 2 { $e }
    |         ^^ lifetime 'x already in scope
@@ -161,7 +161,7 @@
    |         ------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:72:5
+  --> $DIR/hygienic-labels.rs:73:5
    |
 LL |     'x: for _ in 0..1 {
    |     -- first declared here
@@ -170,7 +170,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:72:5
+  --> $DIR/hygienic-labels.rs:73:5
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -179,7 +179,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:72:5
+  --> $DIR/hygienic-labels.rs:73:5
    |
 LL |     'x: loop {
    |     -- first declared here
@@ -188,7 +188,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:72:5
+  --> $DIR/hygienic-labels.rs:73:5
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -197,7 +197,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:72:5
+  --> $DIR/hygienic-labels.rs:73:5
    |
 LL |     'x: while 1 + 1 == 2 {
    |     -- first declared here
@@ -206,7 +206,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:72:5
+  --> $DIR/hygienic-labels.rs:73:5
    |
 LL |         'x: while 1 + 1 == 2 { $e }
    |         -- first declared here
@@ -215,7 +215,7 @@
    |     ^^ lifetime 'x already in scope
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:23:9
+  --> $DIR/hygienic-labels.rs:24:9
    |
 LL |         'x: for _ in 0..1 { $e }
    |         ^^ lifetime 'x already in scope
@@ -227,7 +227,7 @@
    |         ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:23:9
+  --> $DIR/hygienic-labels.rs:24:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -239,7 +239,7 @@
    |         ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:23:9
+  --> $DIR/hygienic-labels.rs:24:9
    |
 LL |         'x: for _ in 0..1 { $e }
    |         ^^ lifetime 'x already in scope
@@ -251,7 +251,7 @@
    |         ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:23:9
+  --> $DIR/hygienic-labels.rs:24:9
    |
 LL |         'x: loop { $e }
    |         -- first declared here
@@ -263,7 +263,7 @@
    |         ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:23:9
+  --> $DIR/hygienic-labels.rs:24:9
    |
 LL |         'x: for _ in 0..1 { $e }
    |         ^^ lifetime 'x already in scope
@@ -275,7 +275,7 @@
    |         ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:23:9
+  --> $DIR/hygienic-labels.rs:24:9
    |
 LL |         'x: for _ in 0..1 { $e }
    |         ^^ lifetime 'x already in scope
@@ -287,7 +287,7 @@
    |         ----------------------- in this macro invocation
 
 warning: label name `'x` shadows a label name that is already in scope
-  --> $DIR/hygienic-labels.rs:23:9
+  --> $DIR/hygienic-labels.rs:24:9
    |
 LL |         'x: for _ in 0..1 { $e }
    |         ^^ lifetime 'x already in scope
diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
index 5e80c67..3300293 100644
--- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
@@ -9,13 +9,21 @@
    |
 LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
    |                          ^^
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<dyn std::fmt::Debug>
-              found std::boxed::Box<(dyn std::fmt::Debug + 'a)>
+note: ...so that the expression is assignable
+  --> $DIR/dyn-trait.rs:20:16
+   |
+LL |     static_val(x);
+   |                ^
+   = note: expected  `std::boxed::Box<dyn std::fmt::Debug>`
+              found  `std::boxed::Box<(dyn std::fmt::Debug + 'a)>`
    = note: but, the lifetime must be valid for the static lifetime...
-   = note: ...so that the types are compatible:
-           expected StaticTrait
-              found StaticTrait
+note: ...so that the types are compatible
+  --> $DIR/dyn-trait.rs:20:5
+   |
+LL |     static_val(x);
+   |     ^^^^^^^^^^
+   = note: expected  `StaticTrait`
+              found  `StaticTrait`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr
new file mode 100644
index 0000000..72e8fa3
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/error-handling.rs:13:56
+   |
+LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
+   |        --  -- lifetime `'b` defined here               ^^^^^^^^^ opaque type requires that `'a` must outlive `'b`
+   |        |
+   |        lifetime `'a` defined here
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr
index ff92d01..5f2dd72 100644
--- a/src/test/ui/issues/issue-12028.stderr
+++ b/src/test/ui/issues/issue-12028.stderr
@@ -1,8 +1,10 @@
-error[E0284]: type annotations needed: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S`
+error[E0284]: type annotations needed
   --> $DIR/issue-12028.rs:27:14
    |
 LL |         self.input_stream(&mut stream);
-   |              ^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^ cannot infer type for type parameter `H`
+   |
+   = note: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-16683.stderr b/src/test/ui/issues/issue-16683.stderr
index b663e21..99700f2 100644
--- a/src/test/ui/issues/issue-16683.stderr
+++ b/src/test/ui/issues/issue-16683.stderr
@@ -21,9 +21,13 @@
    |
 LL | trait T<'a> {
    |         ^^
-   = note: ...so that the types are compatible:
-           expected &'a Self
-              found &Self
+note: ...so that the types are compatible
+  --> $DIR/issue-16683.rs:4:14
+   |
+LL |         self.a();
+   |              ^
+   = note: expected  `&'a Self`
+              found  `&Self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-16966.stderr b/src/test/ui/issues/issue-16966.stderr
index 13e77fe..0d565af 100644
--- a/src/test/ui/issues/issue-16966.stderr
+++ b/src/test/ui/issues/issue-16966.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-16966.rs:2:5
    |
 LL |     panic!(std::default::Default::default());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `M`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `M`
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
diff --git a/src/test/ui/issues/issue-17551.stderr b/src/test/ui/issues/issue-17551.stderr
index ce16f0f..5468268 100644
--- a/src/test/ui/issues/issue-17551.stderr
+++ b/src/test/ui/issues/issue-17551.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-17551.rs:6:15
    |
 LL |     let foo = B(marker::PhantomData);
-   |         ---   ^ cannot infer type for `T`
+   |         ---   ^ cannot infer type for type parameter `T`
    |         |
    |         consider giving `foo` the explicit type `B<T>`, where the type parameter `T` is specified
 
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/issues/issue-17718-const-bad-values.stderr
index 8d875d3..7e4a62a 100644
--- a/src/test/ui/issues/issue-17718-const-bad-values.stderr
+++ b/src/test/ui/issues/issue-17718-const-bad-values.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
   --> $DIR/issue-17718-const-bad-values.rs:1:34
    |
 LL | const C1: &'static mut [usize] = &mut [];
    |                                  ^^^^^^^ constants require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0013]: constants cannot refer to statics, use a constant instead
   --> $DIR/issue-17718-const-bad-values.rs:5:46
@@ -10,13 +13,16 @@
 LL | const C2: &'static mut usize = unsafe { &mut S };
    |                                              ^
 
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
   --> $DIR/issue-17718-const-bad-values.rs:5:41
    |
 LL | const C2: &'static mut usize = unsafe { &mut S };
    |                                         ^^^^^^ constants require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0013, E0017.
+Some errors have detailed explanations: E0013, E0658.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-17758.stderr b/src/test/ui/issues/issue-17758.stderr
index adcbb62..adfc3f508 100644
--- a/src/test/ui/issues/issue-17758.stderr
+++ b/src/test/ui/issues/issue-17758.stderr
@@ -22,9 +22,13 @@
    |
 LL | trait Foo<'a> {
    |           ^^
-   = note: ...so that the types are compatible:
-           expected &'a Self
-              found &Self
+note: ...so that the types are compatible
+  --> $DIR/issue-17758.rs:7:14
+   |
+LL |         self.foo();
+   |              ^^^
+   = note: expected  `&'a Self`
+              found  `&Self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr
index 13c9c09..c7fd134 100644
--- a/src/test/ui/issues/issue-20831-debruijn.stderr
+++ b/src/test/ui/issues/issue-20831-debruijn.stderr
@@ -88,9 +88,19 @@
    |
 LL | impl<'a> Publisher<'a> for MyStruct<'a> {
    |      ^^
-   = note: ...so that the types are compatible:
-           expected Publisher<'_>
-              found Publisher<'_>
+note: ...so that the types are compatible
+  --> $DIR/issue-20831-debruijn.rs:28:5
+   |
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
+   = note: expected  `Publisher<'_>`
+              found  `Publisher<'_>`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr
index 7ceb2bd..b1536bd 100644
--- a/src/test/ui/issues/issue-21974.stderr
+++ b/src/test/ui/issues/issue-21974.stderr
@@ -1,4 +1,4 @@
-error[E0283]: type annotations needed: cannot resolve `&'a T: Foo`
+error[E0283]: type annotations needed
   --> $DIR/issue-21974.rs:10:1
    |
 LL |   trait Foo {
@@ -11,7 +11,9 @@
 LL | |     x.foo();
 LL | |     y.foo();
 LL | | }
-   | |_^
+   | |_^ cannot infer type for reference `&'a T`
+   |
+   = note: cannot resolve `&'a T: Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-2216.rs b/src/test/ui/issues/issue-2216.rs
index fa712ed..ad54107 100644
--- a/src/test/ui/issues/issue-2216.rs
+++ b/src/test/ui/issues/issue-2216.rs
@@ -5,7 +5,7 @@
 
     'foo: loop {
         'bar: loop {
-            'quux: loop {
+            loop {
                 if 1 == 2 {
                     break 'foo;
                 }
diff --git a/src/test/ui/issues/issue-24424.rs b/src/test/ui/issues/issue-24424.rs
index 9b74cd1..22bf513 100644
--- a/src/test/ui/issues/issue-24424.rs
+++ b/src/test/ui/issues/issue-24424.rs
@@ -2,6 +2,6 @@
 trait Trait0<'l0>  {}
 
 impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
-//~^ ERROR type annotations needed: cannot resolve `T0: Trait0<'l0>`
+//~^ ERROR type annotations needed
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr
index 8c539f7..8f08503 100644
--- a/src/test/ui/issues/issue-24424.stderr
+++ b/src/test/ui/issues/issue-24424.stderr
@@ -1,11 +1,13 @@
-error[E0283]: type annotations needed: cannot resolve `T0: Trait0<'l0>`
+error[E0283]: type annotations needed
   --> $DIR/issue-24424.rs:4:1
    |
 LL | trait Trait0<'l0>  {}
    | ----------------- required by `Trait0`
 LL | 
 LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T0`
+   |
+   = note: cannot resolve `T0: Trait0<'l0>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr
index 0b890b5..de020d4 100644
--- a/src/test/ui/issues/issue-25368.stderr
+++ b/src/test/ui/issues/issue-25368.stderr
@@ -5,7 +5,7 @@
    |         -------- consider giving this pattern the explicit type `(std::sync::mpsc::Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)`, where the type parameter `T` is specified
 ...
 LL |         tx.send(Foo{ foo: PhantomData });
-   |                 ^^^ cannot infer type for `T`
+   |                 ^^^ cannot infer type for type parameter `T`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-29147.rs b/src/test/ui/issues/issue-29147.rs
index 7ec96b9..271bc52 100644
--- a/src/test/ui/issues/issue-29147.rs
+++ b/src/test/ui/issues/issue-29147.rs
@@ -18,5 +18,5 @@
 impl Foo for S5<u64> { fn xxx(&self) {} }
 
 fn main() {
-    let _ = <S5<_>>::xxx; //~ ERROR cannot resolve `S5<_>: Foo`
+    let _ = <S5<_>>::xxx; //~ ERROR type annotations needed
 }
diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr
index c9dd92f..1efedb4 100644
--- a/src/test/ui/issues/issue-29147.stderr
+++ b/src/test/ui/issues/issue-29147.stderr
@@ -1,11 +1,13 @@
-error[E0283]: type annotations needed: cannot resolve `S5<_>: Foo`
+error[E0283]: type annotations needed
   --> $DIR/issue-29147.rs:21:13
    |
 LL | trait Foo { fn xxx(&self); }
    |             -------------- required by `Foo::xxx`
 ...
 LL |     let _ = <S5<_>>::xxx;
-   |             ^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^ cannot infer type for struct `S5<_>`
+   |
+   = note: cannot resolve `S5<_>: Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3601.stderr b/src/test/ui/issues/issue-3601.stderr
index fa0fa334..445eb41 100644
--- a/src/test/ui/issues/issue-3601.stderr
+++ b/src/test/ui/issues/issue-3601.stderr
@@ -1,8 +1,8 @@
-error[E0004]: non-exhaustive patterns: `_` not covered
+error[E0004]: non-exhaustive patterns: `Box(_)` not covered
   --> $DIR/issue-3601.rs:30:44
    |
 LL |         box NodeKind::Element(ed) => match ed.kind {
-   |                                            ^^^^^^^ pattern `_` not covered
+   |                                            ^^^^^^^ pattern `Box(_)` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr
index 2c57b85..d90eb53 100644
--- a/src/test/ui/issues/issue-43623.stderr
+++ b/src/test/ui/issues/issue-43623.stderr
@@ -25,4 +25,5 @@
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-46604.rs b/src/test/ui/issues/issue-46604.rs
index 4f1ad38..e1967eb 100644
--- a/src/test/ui/issues/issue-46604.rs
+++ b/src/test/ui/issues/issue-46604.rs
@@ -1,4 +1,4 @@
-static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //~ ERROR E0017
+static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //~ ERROR E0658
 fn write<T: AsRef<[u8]>>(buffer: T) { }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-46604.stderr b/src/test/ui/issues/issue-46604.stderr
index c72f580..32c7ecb 100644
--- a/src/test/ui/issues/issue-46604.stderr
+++ b/src/test/ui/issues/issue-46604.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
   --> $DIR/issue-46604.rs:1:25
    |
 LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
    |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
   --> $DIR/issue-46604.rs:6:5
@@ -12,5 +15,5 @@
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0017, E0594.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0594, E0658.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-5062.stderr b/src/test/ui/issues/issue-5062.stderr
index 0f5c6d8..a20118d 100644
--- a/src/test/ui/issues/issue-5062.stderr
+++ b/src/test/ui/issues/issue-5062.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-5062.rs:1:29
    |
 LL | fn main() { format!("{:?}", None); }
-   |                             ^^^^ cannot infer type for `T`
+   |                             ^^^^ cannot infer type for type parameter `T`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
index aef6dc5..9ca983d 100644
--- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
+++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
@@ -2,13 +2,18 @@
   --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
    |
 LL |     missing_discourses()?
-   |     ^^^^^^^^^^^^^^^^^^^^-
-   |     |                   |
-   |     |                   help: try removing this `?`
-   |     expected enum `std::result::Result`, found `isize`
+   |     ^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `isize`
    |
    = note: expected enum `std::result::Result<isize, ()>`
               found type `isize`
+help: try removing this `?`
+   |
+LL |     missing_discourses()
+   |                        --
+help: try using a variant of the expected enum
+   |
+LL |     Ok(missing_discourses()?)
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-52213.stderr b/src/test/ui/issues/issue-52213.stderr
index b79a5dd..a8960f7 100644
--- a/src/test/ui/issues/issue-52213.stderr
+++ b/src/test/ui/issues/issue-52213.stderr
@@ -9,9 +9,13 @@
    |
 LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
    |                       ^^
-   = note: ...so that the types are compatible:
-           expected (&&(T,),)
-              found (&&'a (T,),)
+note: ...so that the types are compatible
+  --> $DIR/issue-52213.rs:2:11
+   |
+LL |     match (&t,) {
+   |           ^^^^^
+   = note: expected  `(&&(T,),)`
+              found  `(&&'a (T,),)`
 note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 1:27...
   --> $DIR/issue-52213.rs:1:27
    |
diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs
index e7221e2..68d8380 100644
--- a/src/test/ui/issues/issue-54348.rs
+++ b/src/test/ui/issues/issue-54348.rs
@@ -1,7 +1,5 @@
 fn main() {
     [1][0u64 as usize];
     [1][1.5 as usize]; //~ ERROR index out of bounds
-    //~| ERROR this expression will panic at runtime
     [1][1u64 as usize]; //~ ERROR index out of bounds
-    //~| ERROR this expression will panic at runtime
 }
diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr
index 79320ef..fa77bd6 100644
--- a/src/test/ui/issues/issue-54348.stderr
+++ b/src/test/ui/issues/issue-54348.stderr
@@ -6,23 +6,11 @@
    |
    = note: `#[deny(const_err)]` on by default
 
-error: this expression will panic at runtime
-  --> $DIR/issue-54348.rs:3:5
-   |
-LL |     [1][1.5 as usize];
-   |     ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
-
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/issue-54348.rs:5:5
+  --> $DIR/issue-54348.rs:4:5
    |
 LL |     [1][1u64 as usize];
    |     ^^^^^^^^^^^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-54348.rs:5:5
-   |
-LL |     [1][1u64 as usize];
-   |     ^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr
index 56ccdaf..d99a5772 100644
--- a/src/test/ui/issues/issue-54954.stderr
+++ b/src/test/ui/issues/issue-54954.stderr
@@ -4,14 +4,16 @@
 LL |     const fn const_val<T: Sized>() -> usize {
    |     ^^^^^ trait fns cannot be const
 
-error[E0283]: type annotations needed: cannot resolve `_: Tt`
+error[E0283]: type annotations needed
   --> $DIR/issue-54954.rs:3:24
    |
 LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
 ...
 LL |     const fn const_val<T: Sized>() -> usize {
    |              --------- - required by this bound in `Tt::const_val`
+   |
+   = note: cannot resolve `_: Tt`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-54954.rs:13:15
diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr
index 7b910f5..b8cafdc 100644
--- a/src/test/ui/issues/issue-55796.stderr
+++ b/src/test/ui/issues/issue-55796.stderr
@@ -15,9 +15,13 @@
 LL |         Box::new(self.out_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>
-              found std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>
+note: ...so that the expression is assignable
+  --> $DIR/issue-55796.rs:16:9
+   |
+LL |         Box::new(self.out_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected  `std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>`
+              found  `std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>`
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/issue-55796.rs:21:9
@@ -36,9 +40,13 @@
 LL |         Box::new(self.in_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>
-              found std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>
+note: ...so that the expression is assignable
+  --> $DIR/issue-55796.rs:21:9
+   |
+LL |         Box::new(self.in_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected  `std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>`
+              found  `std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-58022.rs b/src/test/ui/issues/issue-58022.rs
index 3052790..e4b9b3b 100644
--- a/src/test/ui/issues/issue-58022.rs
+++ b/src/test/ui/issues/issue-58022.rs
@@ -2,7 +2,7 @@
     const SIZE: usize;
 
     fn new(slice: &[u8; Foo::SIZE]) -> Self;
-    //~^ ERROR: type annotations needed: cannot resolve `_: Foo`
+    //~^ ERROR: type annotations needed
 }
 
 pub struct Bar<T: ?Sized>(T);
diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr
index a3e4cb6..ef0d66d 100644
--- a/src/test/ui/issues/issue-58022.stderr
+++ b/src/test/ui/issues/issue-58022.stderr
@@ -4,14 +4,16 @@
 LL |         Foo(Box::new(*slice))
    |         ^^^ not a function, tuple struct or tuple variant
 
-error[E0283]: type annotations needed: cannot resolve `_: Foo`
+error[E0283]: type annotations needed
   --> $DIR/issue-58022.rs:4:25
    |
 LL |     const SIZE: usize;
    |     ------------------ required by `Foo::SIZE`
 LL | 
 LL |     fn new(slice: &[u8; Foo::SIZE]) -> Self;
-   |                         ^^^^^^^^^
+   |                         ^^^^^^^^^ cannot infer type
+   |
+   = note: cannot resolve `_: Foo`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-59756.rs b/src/test/ui/issues/issue-59756.rs
index cccae39..d6df059 100644
--- a/src/test/ui/issues/issue-59756.rs
+++ b/src/test/ui/issues/issue-59756.rs
@@ -1,4 +1,8 @@
 // run-rustfix
+// ignore-test
+//
+// FIXME: Re-enable this test once we support choosing
+// between multiple mutually exclusive suggestions for the same span
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/issues/issue-59756.stderr b/src/test/ui/issues/issue-59756.stderr
index 150916c..9066e57 100644
--- a/src/test/ui/issues/issue-59756.stderr
+++ b/src/test/ui/issues/issue-59756.stderr
@@ -2,13 +2,18 @@
   --> $DIR/issue-59756.rs:13:5
    |
 LL |     foo()?
-   |     ^^^^^-
-   |     |    |
-   |     |    help: try removing this `?`
-   |     expected enum `std::result::Result`, found struct `A`
+   |     ^^^^^^ expected enum `std::result::Result`, found struct `A`
    |
    = note: expected enum `std::result::Result<A, B>`
             found struct `A`
+help: try removing this `?`
+   |
+LL |     foo()
+   |         --
+help: try using a variant of the expected enum
+   |
+LL |     Ok(foo()?)
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr
index 69c1d85..d13dcd5 100644
--- a/src/test/ui/issues/issue-60283.stderr
+++ b/src/test/ui/issues/issue-60283.stderr
@@ -27,4 +27,5 @@
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-6458-2.stderr b/src/test/ui/issues/issue-6458-2.stderr
index b5da2bf..d538a69 100644
--- a/src/test/ui/issues/issue-6458-2.stderr
+++ b/src/test/ui/issues/issue-6458-2.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-6458-2.rs:3:21
    |
 LL |     format!("{:?}", None);
-   |                     ^^^^ cannot infer type for `T`
+   |                     ^^^^ cannot infer type for type parameter `T`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-6458-3.stderr b/src/test/ui/issues/issue-6458-3.stderr
index 784497c..6b3f469 100644
--- a/src/test/ui/issues/issue-6458-3.stderr
+++ b/src/test/ui/issues/issue-6458-3.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-6458-3.rs:4:5
    |
 LL |     mem::transmute(0);
-   |     ^^^^^^^^^^^^^^ cannot infer type for `U`
+   |     ^^^^^^^^^^^^^^ cannot infer type for type parameter `U`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-6458.stderr b/src/test/ui/issues/issue-6458.stderr
index d59d872..de31565 100644
--- a/src/test/ui/issues/issue-6458.stderr
+++ b/src/test/ui/issues/issue-6458.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-6458.rs:9:4
    |
 LL |    foo(TypeWithState(marker::PhantomData));
-   |    ^^^ cannot infer type for `State`
+   |    ^^^ cannot infer type for type parameter `State`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/issues/issue-65611.stderr
index cb441c1..20e2ba1 100644
--- a/src/test/ui/issues/issue-65611.stderr
+++ b/src/test/ui/issues/issue-65611.stderr
@@ -2,7 +2,10 @@
   --> $DIR/issue-65611.rs:59:20
    |
 LL |     let x = buffer.last().unwrap().0.clone();
-   |                    ^^^^ cannot infer type for `T`
+   |             -------^^^^--
+   |             |      |
+   |             |      cannot infer type for type parameter `T`
+   |             this method call resolves to `std::option::Option<&T>`
    |
    = note: type must be known at this point
 
diff --git a/src/test/ui/issues/issue-65634-raw-ident-suggestion.rs b/src/test/ui/issues/issue-65634-raw-ident-suggestion.rs
new file mode 100644
index 0000000..b928510
--- /dev/null
+++ b/src/test/ui/issues/issue-65634-raw-ident-suggestion.rs
@@ -0,0 +1,22 @@
+#![allow(non_camel_case_types)]
+
+trait r#async {
+    fn r#struct(&self) {
+        println!("async");
+    }
+}
+
+trait r#await {
+    fn r#struct(&self) {
+        println!("await");
+    }
+}
+
+struct r#fn {}
+
+impl r#async for r#fn {}
+impl r#await for r#fn {}
+
+fn main() {
+    r#fn {}.r#struct(); //~ ERROR multiple applicable items in scope
+}
diff --git a/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr b/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr
new file mode 100644
index 0000000..c7bb653
--- /dev/null
+++ b/src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr
@@ -0,0 +1,22 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/issue-65634-raw-ident-suggestion.rs:21:13
+   |
+LL |     r#fn {}.r#struct();
+   |             ^^^^^^^^ multiple `r#struct` found
+   |
+note: candidate #1 is defined in an impl of the trait `async` for the type `r#fn`
+  --> $DIR/issue-65634-raw-ident-suggestion.rs:4:5
+   |
+LL |     fn r#struct(&self) {
+   |     ^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `async::r#struct(r#fn {})` instead
+note: candidate #2 is defined in an impl of the trait `await` for the type `r#fn`
+  --> $DIR/issue-65634-raw-ident-suggestion.rs:10:5
+   |
+LL |     fn r#struct(&self) {
+   |     ^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `await::r#struct(r#fn {})` instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/issues/issue-66702-break-outside-loop-val.rs b/src/test/ui/issues/issue-66702-break-outside-loop-val.rs
new file mode 100644
index 0000000..bd3c00d
--- /dev/null
+++ b/src/test/ui/issues/issue-66702-break-outside-loop-val.rs
@@ -0,0 +1,7 @@
+// Breaks with values inside closures used to ICE (#66863)
+
+fn main() {
+    'some_label: loop {
+        || break 'some_label (); //~ ERROR: `break` inside of a closure
+    }
+}
diff --git a/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr b/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr
new file mode 100644
index 0000000..83bde97
--- /dev/null
+++ b/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr
@@ -0,0 +1,11 @@
+error[E0267]: `break` inside of a closure
+  --> $DIR/issue-66702-break-outside-loop-val.rs:5:12
+   |
+LL |         || break 'some_label ();
+   |         -- ^^^^^^^^^^^^^^^^^^^^ cannot `break` inside of a closure
+   |         |
+   |         enclosing closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0267`.
diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
new file mode 100644
index 0000000..44bd645
--- /dev/null
+++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
@@ -0,0 +1,21 @@
+// Regression test for #67037.
+//
+// In type checking patterns, E0023 occurs when the tuple pattern and the expected
+// tuple pattern have different number of fields. For example, as below, `P()`,
+// the tuple struct pattern, has 0 fields, but requires 1 field.
+//
+// In emitting E0023, we try to see if this is a case of e.g., `Some(a, b, c)` but where
+// the scrutinee was of type `Some((a, b, c))`, and suggest that parenthesis be added.
+//
+// However, we did not account for the expected type being different than the tuple pattern type.
+// This caused an issue when the tuple pattern type (`P<T>`) was generic.
+// Specifically, we tried deriving the 0th field's type using the `substs` of the expected type.
+// When attempting to substitute `T`, there was no such substitution, so "out of range" occured.
+
+struct U {} // 0 type parameters offered
+struct P<T>(T); // 1 type parameter wanted
+
+fn main() {
+    let P() = U {}; //~ ERROR mismatched types
+    //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 1 field
+}
diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
new file mode 100644
index 0000000..521dd02
--- /dev/null
+++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9
+   |
+LL |     let P() = U {};
+   |         ^^^ expected struct `U`, found struct `P`
+   |
+   = note: expected struct `U`
+              found struct `P<_>`
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 1 field
+  --> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9
+   |
+LL | struct P<T>(T); // 1 type parameter wanted
+   | --------------- tuple struct defined here
+...
+LL |     let P() = U {};
+   |         ^^^ expected 1 field, found 0
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0023, E0308.
+For more information about an error, try `rustc --explain E0023`.
diff --git a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.rs b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.rs
new file mode 100644
index 0000000..a496e58
--- /dev/null
+++ b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.rs
@@ -0,0 +1,27 @@
+// Pin's PartialEq implementation allowed to access the pointer allowing for
+// unsoundness by using Rc::get_mut to move value within Rc.
+// See https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73 for more details.
+
+use std::ops::Deref;
+use std::pin::Pin;
+use std::rc::Rc;
+
+struct Apple;
+
+impl Deref for Apple {
+    type Target = Apple;
+    fn deref(&self) -> &Apple {
+        &Apple
+    }
+}
+
+impl PartialEq<Rc<Apple>> for Apple {
+    fn eq(&self, _rc: &Rc<Apple>) -> bool {
+        unreachable!()
+    }
+}
+
+fn main() {
+    let _ = Pin::new(Apple) == Rc::pin(Apple);
+    //~^ ERROR type mismatch resolving
+}
diff --git a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr
new file mode 100644
index 0000000..3330d60
--- /dev/null
+++ b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr
@@ -0,0 +1,13 @@
+error[E0271]: type mismatch resolving `<std::rc::Rc<Apple> as std::ops::Deref>::Target == std::rc::Rc<Apple>`
+  --> $DIR/issue-67039-unsound-pin-partialeq.rs:25:29
+   |
+LL |     let _ = Pin::new(Apple) == Rc::pin(Apple);
+   |                             ^^ expected struct `Apple`, found struct `std::rc::Rc`
+   |
+   = note: expected type `Apple`
+            found struct `std::rc::Rc<Apple>`
+   = note: required because of the requirements on the impl of `std::cmp::PartialEq<std::pin::Pin<std::rc::Rc<Apple>>>` for `std::pin::Pin<Apple>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs
index 4637814..71e2b58 100644
--- a/src/test/ui/issues/issue-8460-const.rs
+++ b/src/test/ui/issues/issue-8460-const.rs
@@ -23,19 +23,14 @@
     //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
     //~| ERROR this expression will panic at runtime
@@ -53,17 +48,12 @@
     //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
 }
diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr
index 7e5a22e..c6750e6 100644
--- a/src/test/ui/issues/issue-8460-const.stderr
+++ b/src/test/ui/issues/issue-8460-const.stderr
@@ -70,179 +70,119 @@
 LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:24:36
-   |
-LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to divide by zero
-
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:27:36
+  --> $DIR/issue-8460-const.rs:26:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
    |                                    ^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:27:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to divide by zero
-
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:30:36
+  --> $DIR/issue-8460-const.rs:28:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
-error: this expression will panic at runtime
+error: attempt to divide by zero
   --> $DIR/issue-8460-const.rs:30:36
    |
-LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide by zero
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:33:36
-   |
 LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:33:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide by zero
-
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:36:36
+  --> $DIR/issue-8460-const.rs:32:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:36:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide by zero
-
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:39:36
+  --> $DIR/issue-8460-const.rs:34:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:39:36
+  --> $DIR/issue-8460-const.rs:34:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:42:36
+  --> $DIR/issue-8460-const.rs:37:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:42:36
+  --> $DIR/issue-8460-const.rs:37:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:45:36
+  --> $DIR/issue-8460-const.rs:40:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:45:36
+  --> $DIR/issue-8460-const.rs:40:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:48:36
+  --> $DIR/issue-8460-const.rs:43:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:48:36
+  --> $DIR/issue-8460-const.rs:43:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:51:36
+  --> $DIR/issue-8460-const.rs:46:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:51:36
+  --> $DIR/issue-8460-const.rs:46:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:54:36
+  --> $DIR/issue-8460-const.rs:49:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:54:36
-   |
-LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:57:36
+  --> $DIR/issue-8460-const.rs:51:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
    |                                    ^^^^^^^
 
-error: this expression will panic at runtime
+error: attempt to calculate the remainder with a divisor of zero
+  --> $DIR/issue-8460-const.rs:53:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: attempt to calculate the remainder with a divisor of zero
+  --> $DIR/issue-8460-const.rs:55:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: attempt to calculate the remainder with a divisor of zero
   --> $DIR/issue-8460-const.rs:57:36
    |
-LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:60:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:60:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:63:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:63:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:66:36
-   |
 LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
    |                                    ^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:66:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
-error: aborting due to 40 previous errors
+error: aborting due to 30 previous errors
 
diff --git a/src/test/ui/issues/issue-8460-const2.rs b/src/test/ui/issues/issue-8460-const2.rs
index c3f53e3..723a179 100644
--- a/src/test/ui/issues/issue-8460-const2.rs
+++ b/src/test/ui/issues/issue-8460-const2.rs
@@ -18,19 +18,14 @@
     //~^ ERROR attempt to divide with overflow
     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
@@ -43,17 +38,12 @@
     //~^ ERROR attempt to calculate the remainder with overflow
     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR this expression will panic at runtime
 }
diff --git a/src/test/ui/issues/issue-8460-const2.stderr b/src/test/ui/issues/issue-8460-const2.stderr
index b688ec1..87b9b2d 100644
--- a/src/test/ui/issues/issue-8460-const2.stderr
+++ b/src/test/ui/issues/issue-8460-const2.stderr
@@ -40,149 +40,89 @@
 LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const2.rs:19:36
-   |
-LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to divide by zero
-
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:22:36
+  --> $DIR/issue-8460-const2.rs:21:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
    |                                    ^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const2.rs:22:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to divide by zero
-
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:25:36
+  --> $DIR/issue-8460-const2.rs:23:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
-error: this expression will panic at runtime
+error: attempt to divide by zero
   --> $DIR/issue-8460-const2.rs:25:36
    |
-LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide by zero
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:28:36
-   |
 LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const2.rs:28:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide by zero
-
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:31:36
+  --> $DIR/issue-8460-const2.rs:27:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const2.rs:31:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide by zero
-
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:34:36
+  --> $DIR/issue-8460-const2.rs:29:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:36:36
+  --> $DIR/issue-8460-const2.rs:31:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:38:36
+  --> $DIR/issue-8460-const2.rs:33:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:40:36
+  --> $DIR/issue-8460-const2.rs:35:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:42:36
+  --> $DIR/issue-8460-const2.rs:37:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:44:36
+  --> $DIR/issue-8460-const2.rs:39:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const2.rs:44:36
-   |
-LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:47:36
+  --> $DIR/issue-8460-const2.rs:41:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
    |                                    ^^^^^^^
 
-error: this expression will panic at runtime
+error: attempt to calculate the remainder with a divisor of zero
+  --> $DIR/issue-8460-const2.rs:43:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: attempt to calculate the remainder with a divisor of zero
+  --> $DIR/issue-8460-const2.rs:45:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: attempt to calculate the remainder with a divisor of zero
   --> $DIR/issue-8460-const2.rs:47:36
    |
-LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:50:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const2.rs:50:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:53:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const2.rs:53:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:56:36
-   |
 LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
    |                                    ^^^^^^^^
 
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const2.rs:56:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
-
-error: aborting due to 30 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
index ab9baa7..0a951cf 100644
--- a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
+++ b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
@@ -17,10 +17,7 @@
 
 macro_rules! and_the_heavens_reject_not {
     () => {
-        // ↓ But let's test that we still lint for unused parens around
-        // function args inside of simple, one-deep macros.
         #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
-        //~^ WARN unnecessary parentheses around function argument
     }
 }
 
diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr
deleted file mode 100644
index 57cdcd7..0000000
--- a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-warning: unnecessary parentheses around function argument
-  --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:22:83
-   |
-LL |         #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
-   |                                                                                   ^^^ help: remove these parentheses
-...
-LL | and_the_heavens_reject_not!();
-   | ------------------------------ in this macro invocation
-   |
-note: lint level defined here
-  --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:3:9
-   |
-LL | #![warn(unused_parens)]
-   |         ^^^^^^^^^^^^^
-
diff --git a/src/test/ui/lint/lint-unnecessary-parens.rs b/src/test/ui/lint/lint-unnecessary-parens.rs
index 9f42b85..12ffb6d 100644
--- a/src/test/ui/lint/lint-unnecessary-parens.rs
+++ b/src/test/ui/lint/lint-unnecessary-parens.rs
@@ -25,6 +25,12 @@
     panic!()
 }
 
+macro_rules! baz {
+    ($($foo:expr),+) => {
+        ($($foo),*)
+    }
+}
+
 fn main() {
     foo();
     bar((true)); //~ ERROR unnecessary parentheses around function argument
@@ -55,4 +61,7 @@
     let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value
     _a = (0); //~ ERROR unnecessary parentheses around assigned value
     _a += (1); //~ ERROR unnecessary parentheses around assigned value
+
+    let _a = baz!(3, 4);
+    let _b = baz!(3);
 }
diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr
index adc1069..541ae7a 100644
--- a/src/test/ui/lint/lint-unnecessary-parens.stderr
+++ b/src/test/ui/lint/lint-unnecessary-parens.stderr
@@ -23,25 +23,25 @@
    |                                          ^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around function argument
-  --> $DIR/lint-unnecessary-parens.rs:30:9
+  --> $DIR/lint-unnecessary-parens.rs:36:9
    |
 LL |     bar((true));
    |         ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `if` condition
-  --> $DIR/lint-unnecessary-parens.rs:32:8
+  --> $DIR/lint-unnecessary-parens.rs:38:8
    |
 LL |     if (true) {}
    |        ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `while` condition
-  --> $DIR/lint-unnecessary-parens.rs:33:11
+  --> $DIR/lint-unnecessary-parens.rs:39:11
    |
 LL |     while (true) {}
    |           ^^^^^^ help: remove these parentheses
 
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/lint-unnecessary-parens.rs:33:5
+  --> $DIR/lint-unnecessary-parens.rs:39:5
    |
 LL |     while (true) {}
    |     ^^^^^^^^^^^^ help: use `loop`
@@ -49,43 +49,43 @@
    = note: `#[warn(while_true)]` on by default
 
 error: unnecessary parentheses around `match` head expression
-  --> $DIR/lint-unnecessary-parens.rs:35:11
+  --> $DIR/lint-unnecessary-parens.rs:41:11
    |
 LL |     match (true) {
    |           ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `let` head expression
-  --> $DIR/lint-unnecessary-parens.rs:38:16
+  --> $DIR/lint-unnecessary-parens.rs:44:16
    |
 LL |     if let 1 = (1) {}
    |                ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `let` head expression
-  --> $DIR/lint-unnecessary-parens.rs:39:19
+  --> $DIR/lint-unnecessary-parens.rs:45:19
    |
 LL |     while let 1 = (2) {}
    |                   ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around method argument
-  --> $DIR/lint-unnecessary-parens.rs:53:24
+  --> $DIR/lint-unnecessary-parens.rs:59:24
    |
 LL |     X { y: false }.foo((true));
    |                        ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:55:18
+  --> $DIR/lint-unnecessary-parens.rs:61:18
    |
 LL |     let mut _a = (0);
    |                  ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:56:10
+  --> $DIR/lint-unnecessary-parens.rs:62:10
    |
 LL |     _a = (0);
    |          ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:57:11
+  --> $DIR/lint-unnecessary-parens.rs:63:11
    |
 LL |     _a += (1);
    |           ^^^ help: remove these parentheses
diff --git a/src/test/ui/macros/macro-lifetime-used-with-labels.rs b/src/test/ui/macros/macro-lifetime-used-with-labels.rs
index 86a3e9f..2e9da6f 100644
--- a/src/test/ui/macros/macro-lifetime-used-with-labels.rs
+++ b/src/test/ui/macros/macro-lifetime-used-with-labels.rs
@@ -1,6 +1,6 @@
 // run-pass
 #![allow(stable_features)]
-
+#![allow(unused_labels)]
 #![allow(unreachable_code)]
 
 macro_rules! x {
diff --git a/src/test/ui/malformed/malformed-derive-entry.rs b/src/test/ui/malformed/malformed-derive-entry.rs
index a6d8863..77fa2f5 100644
--- a/src/test/ui/malformed/malformed-derive-entry.rs
+++ b/src/test/ui/malformed/malformed-derive-entry.rs
@@ -1,7 +1,11 @@
-#[derive(Copy(Bad))] //~ ERROR expected one of `)`, `,`, or `::`, found `(`
+#[derive(Copy(Bad))]
+//~^ ERROR traits in `#[derive(...)]` don't accept arguments
+//~| ERROR the trait bound
 struct Test1;
 
-#[derive(Copy="bad")] //~ ERROR expected one of `)`, `,`, or `::`, found `=`
+#[derive(Copy="bad")]
+//~^ ERROR traits in `#[derive(...)]` don't accept values
+//~| ERROR the trait bound
 struct Test2;
 
 #[derive] //~ ERROR malformed `derive` attribute input
diff --git a/src/test/ui/malformed/malformed-derive-entry.stderr b/src/test/ui/malformed/malformed-derive-entry.stderr
index 8d750b6..1f1ee39 100644
--- a/src/test/ui/malformed/malformed-derive-entry.stderr
+++ b/src/test/ui/malformed/malformed-derive-entry.stderr
@@ -1,20 +1,33 @@
-error: expected one of `)`, `,`, or `::`, found `(`
+error: traits in `#[derive(...)]` don't accept arguments
   --> $DIR/malformed-derive-entry.rs:1:14
    |
 LL | #[derive(Copy(Bad))]
-   |              ^ expected one of `)`, `,`, or `::`
+   |              ^^^^^ help: remove the arguments
 
-error: expected one of `)`, `,`, or `::`, found `=`
-  --> $DIR/malformed-derive-entry.rs:4:14
+error: traits in `#[derive(...)]` don't accept values
+  --> $DIR/malformed-derive-entry.rs:6:14
    |
 LL | #[derive(Copy="bad")]
-   |              ^ expected one of `)`, `,`, or `::`
+   |              ^^^^^^ help: remove the value
 
 error: malformed `derive` attribute input
-  --> $DIR/malformed-derive-entry.rs:7:1
+  --> $DIR/malformed-derive-entry.rs:11:1
    |
 LL | #[derive]
    | ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]`
 
-error: aborting due to 3 previous errors
+error[E0277]: the trait bound `Test1: std::clone::Clone` is not satisfied
+  --> $DIR/malformed-derive-entry.rs:1:10
+   |
+LL | #[derive(Copy(Bad))]
+   |          ^^^^ the trait `std::clone::Clone` is not implemented for `Test1`
 
+error[E0277]: the trait bound `Test2: std::clone::Clone` is not satisfied
+  --> $DIR/malformed-derive-entry.rs:6:10
+   |
+LL | #[derive(Copy="bad")]
+   |          ^^^^ the trait `std::clone::Clone` is not implemented for `Test2`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/malformed/malformed-meta-delim.rs b/src/test/ui/malformed/malformed-meta-delim.rs
new file mode 100644
index 0000000..5b1614b
--- /dev/null
+++ b/src/test/ui/malformed/malformed-meta-delim.rs
@@ -0,0 +1,11 @@
+fn main() {}
+
+#[allow { foo_lint } ]
+//~^ ERROR wrong meta list delimiters
+//~| HELP the delimiters should be `(` and `)`
+fn delim_brace() {}
+
+#[allow [ foo_lint ] ]
+//~^ ERROR wrong meta list delimiters
+//~| HELP the delimiters should be `(` and `)`
+fn delim_bracket() {}
diff --git a/src/test/ui/malformed/malformed-meta-delim.stderr b/src/test/ui/malformed/malformed-meta-delim.stderr
new file mode 100644
index 0000000..407193d
--- /dev/null
+++ b/src/test/ui/malformed/malformed-meta-delim.stderr
@@ -0,0 +1,24 @@
+error: wrong meta list delimiters
+  --> $DIR/malformed-meta-delim.rs:3:9
+   |
+LL | #[allow { foo_lint } ]
+   |         ^^^^^^^^^^^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL | #[allow ( foo_lint ) ]
+   |         ^          ^
+
+error: wrong meta list delimiters
+  --> $DIR/malformed-meta-delim.rs:8:9
+   |
+LL | #[allow [ foo_lint ] ]
+   |         ^^^^^^^^^^^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL | #[allow ( foo_lint ) ]
+   |         ^          ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/malformed/malformed-special-attrs.rs b/src/test/ui/malformed/malformed-special-attrs.rs
index e67fbdd..05b7ebe 100644
--- a/src/test/ui/malformed/malformed-special-attrs.rs
+++ b/src/test/ui/malformed/malformed-special-attrs.rs
@@ -1,7 +1,7 @@
 #[cfg_attr] //~ ERROR malformed `cfg_attr` attribute
 struct S1;
 
-#[cfg_attr = ""] //~ ERROR expected `(`, found `=`
+#[cfg_attr = ""] //~ ERROR malformed `cfg_attr` attribute
 struct S2;
 
 #[derive] //~ ERROR malformed `derive` attribute
diff --git a/src/test/ui/malformed/malformed-special-attrs.stderr b/src/test/ui/malformed/malformed-special-attrs.stderr
index 319c05e..6f535e0 100644
--- a/src/test/ui/malformed/malformed-special-attrs.stderr
+++ b/src/test/ui/malformed/malformed-special-attrs.stderr
@@ -6,11 +6,13 @@
    |
    = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
 
-error: expected `(`, found `=`
-  --> $DIR/malformed-special-attrs.rs:4:12
+error: malformed `cfg_attr` attribute input
+  --> $DIR/malformed-special-attrs.rs:4:1
    |
 LL | #[cfg_attr = ""]
-   |            ^ expected `(`
+   | ^^^^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
 
 error: malformed `derive` attribute input
   --> $DIR/malformed-special-attrs.rs:7:1
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
index fcd9764..f3f3c47 100644
--- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -2,7 +2,7 @@
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:17
    |
 LL |     let mut x = Vec::new();
-   |         -----   ^^^^^^^^ cannot infer type for `T`
+   |         -----   ^^^^^^^^ cannot infer type for type parameter `T`
    |         |
    |         consider giving `x` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified
 
diff --git a/src/test/ui/mir/issue66339.rs b/src/test/ui/mir/issue66339.rs
new file mode 100644
index 0000000..98e178c
--- /dev/null
+++ b/src/test/ui/mir/issue66339.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Z mir-opt-level=2
+// build-pass
+
+// This used to ICE in const-prop
+
+fn foo() {
+    let bar = |_| { };
+    let _ = bar("a");
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr
index 88c1efd..06f5c05 100644
--- a/src/test/ui/mismatched_types/E0631.stderr
+++ b/src/test/ui/mismatched_types/E0631.stderr
@@ -46,3 +46,4 @@
 
 error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr
index c208187..c731306 100644
--- a/src/test/ui/mismatched_types/abridged.stderr
+++ b/src/test/ui/mismatched_types/abridged.stderr
@@ -26,7 +26,10 @@
 LL | fn b() -> Option<Foo> {
    |           ----------- expected `std::option::Option<Foo>` because of return type
 LL |     Foo { bar: 1 }
-   |     ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo`
+   |     ^^^^^^^^^^^^^^
+   |     |
+   |     expected enum `std::option::Option`, found struct `Foo`
+   |     help: try using a variant of the expected enum: `Some(Foo { bar: 1 })`
    |
    = note: expected enum `std::option::Option<Foo>`
             found struct `Foo`
@@ -37,7 +40,10 @@
 LL | fn c() -> Result<Foo, Bar> {
    |           ---------------- expected `std::result::Result<Foo, Bar>` because of return type
 LL |     Foo { bar: 1 }
-   |     ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo`
+   |     ^^^^^^^^^^^^^^
+   |     |
+   |     expected enum `std::result::Result`, found struct `Foo`
+   |     help: try using a variant of the expected enum: `Ok(Foo { bar: 1 })`
    |
    = note: expected enum `std::result::Result<Foo, Bar>`
             found struct `Foo`
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
index 85cad61..ed50282 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -45,4 +45,5 @@
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index fd2b9f3..f3874c0 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -24,4 +24,5 @@
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
index 1a82dd5..88c9266 100644
--- a/src/test/ui/mismatched_types/fn-variance-1.stderr
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -24,3 +24,4 @@
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index 72f3220..da018aa 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -18,4 +18,5 @@
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0599`.
+Some errors have detailed explanations: E0599, E0631.
+For more information about an error, try `rustc --explain E0599`.
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
index 2daf478..3c999f2 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -12,3 +12,4 @@
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/missing/missing-items/missing-type-parameter.stderr b/src/test/ui/missing/missing-items/missing-type-parameter.stderr
index dbb467d..be97f23 100644
--- a/src/test/ui/missing/missing-items/missing-type-parameter.stderr
+++ b/src/test/ui/missing/missing-items/missing-type-parameter.stderr
@@ -2,7 +2,7 @@
   --> $DIR/missing-type-parameter.rs:4:5
    |
 LL |     foo();
-   |     ^^^ cannot infer type for `X`
+   |     ^^^ cannot infer type for type parameter `X`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index abeffee..3d79ff0 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -4,7 +4,7 @@
 LL |         let mut closure = expect_sig(|p, y| *p = y);
    |                                      ^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:4 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: test::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) mut &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) i32)),
            ]
@@ -30,7 +30,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:3 ~ escape_argument_callee[317d]::test[0]) with substs []
+   = note: defining type: test
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
index f750d15..37f04af 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -4,7 +4,7 @@
 LL |         let mut closure = expect_sig(|p, y| *p = y);
    |                                      ^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:4 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: test::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) mut &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32)),
            ]
@@ -21,7 +21,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:3 ~ escape_argument[317d]::test[0]) with substs []
+   = note: defining type: test
 
 error[E0597]: `y` does not live long enough
   --> $DIR/escape-argument.rs:27:25
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
index 7c4d48c..810c028 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
@@ -4,7 +4,7 @@
 LL |             let mut closure1 = || p = &y;
    |                                ^^^^^^^^^
    |
-   = note: defining type: DefId(0:5 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: test::{{closure}}#0::{{closure}}#0 with closure substs [
                i16,
                extern "rust-call" fn(()),
                &'_#1r i32,
@@ -23,7 +23,7 @@
 LL | |         };
    | |_________^
    |
-   = note: defining type: DefId(0:4 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: test::{{closure}}#0 with closure substs [
                i16,
                extern "rust-call" fn(()),
                &'_#1r i32,
@@ -44,7 +44,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:3 ~ escape_upvar_nested[317d]::test[0]) with substs []
+   = note: defining type: test
 
 error[E0597]: `y` does not live long enough
   --> $DIR/escape-upvar-nested.rs:21:40
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
index 4446486..bf04276 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
@@ -4,7 +4,7 @@
 LL |         let mut closure = || p = &y;
    |                           ^^^^^^^^^
    |
-   = note: defining type: DefId(0:4 ~ escape_upvar_ref[317d]::test[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: test::{{closure}}#0 with closure substs [
                i16,
                extern "rust-call" fn(()),
                &'_#1r i32,
@@ -25,7 +25,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:3 ~ escape_upvar_ref[317d]::test[0]) with substs []
+   = note: defining type: test
 
 error[E0597]: `y` does not live long enough
   --> $DIR/escape-upvar-ref.rs:23:35
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 92f30d4..4e3aa35 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -8,7 +8,7 @@
 LL | |         },
    | |_________^
    |
-   = note: defining type: DefId(0:18 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: supply::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
            ]
@@ -39,7 +39,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:14 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]) with substs []
+   = note: defining type: supply
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index 00bb66a..cd61b8b 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -9,7 +9,7 @@
 LL | |     });
    | |_____^
    |
-   = note: defining type: DefId(0:16 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: supply::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)),
            ]
@@ -30,7 +30,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:13 ~ propagate_approximated_ref[317d]::supply[0]) with substs []
+   = note: defining type: supply
 
 error: lifetime may not live long enough
   --> $DIR/propagate-approximated-ref.rs:45:9
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 2b05503..259140c 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -8,7 +8,7 @@
 LL | |     })
    | |_____^
    |
-   = note: defining type: DefId(0:9 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: case1::{{closure}}#0 with closure substs [
                i32,
                for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>)),
            ]
@@ -35,7 +35,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:8 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]) with substs []
+   = note: defining type: case1
 
 note: External requirements
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:35:15
@@ -46,7 +46,7 @@
 LL | |     })
    | |_____^
    |
-   = note: defining type: DefId(0:11 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: case2::{{closure}}#0 with closure substs [
                i32,
                for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>)),
            ]
@@ -65,7 +65,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:10 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]) with substs []
+   = note: defining type: case2
 
 error[E0597]: `a` does not live long enough
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index ee0f0b7..b3dd682 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -10,7 +10,7 @@
 LL | |     });
    | |_____^
    |
-   = note: defining type: DefId(0:16 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: supply::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t2)) u32>)),
            ]
@@ -31,7 +31,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:13 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs []
+   = note: defining type: supply
 
 error[E0521]: borrowed data escapes outside of function
   --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index 611a129..ab12d08 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -10,7 +10,7 @@
 LL | |     });
    | |_____^
    |
-   = note: defining type: DefId(0:16 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: supply::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)),
            ]
@@ -31,7 +31,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:13 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs []
+   = note: defining type: supply
 
 error[E0521]: borrowed data escapes outside of function
   --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 9328d05..b2209e9 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -9,7 +9,7 @@
 LL | |     });
    | |_____^
    |
-   = note: defining type: DefId(0:16 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: test::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
            ]
@@ -30,7 +30,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:13 ~ propagate_approximated_val[317d]::test[0]) with substs []
+   = note: defining type: test
 
 error: lifetime may not live long enough
   --> $DIR/propagate-approximated-val.rs:38:9
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index afac526..55ee515 100644
--- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -8,7 +8,7 @@
 LL | |         },
    | |_________^
    |
-   = note: defining type: DefId(0:14 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: supply::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
            ]
@@ -28,5 +28,5 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:12 ~ propagate_despite_same_free_region[317d]::supply[0]) with substs []
+   = note: defining type: supply
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index 9699e8f..1c29af8 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -9,7 +9,7 @@
 LL | |     });
    | |_____^
    |
-   = note: defining type: DefId(0:16 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: supply::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
            ]
@@ -39,7 +39,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:13 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]) with substs []
+   = note: defining type: supply
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 2a18079..afa0e9f 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -9,7 +9,7 @@
 LL | |     });
    | |_____^
    |
-   = note: defining type: DefId(0:16 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: supply::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)),
            ]
@@ -39,7 +39,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:13 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]) with substs []
+   = note: defining type: supply
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
index 0d62265..0dbb530 100644
--- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
@@ -11,9 +11,7 @@
 LL | |     });
    | |_____^
    |
-   = note: defining type: DefId(0:14 ~ propagate_from_trait_match[317d]::supply[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: supply::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((T,)),
            ]
@@ -32,10 +30,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:11 ~ propagate_from_trait_match[317d]::supply[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: supply::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/propagate-from-trait-match.rs:32:36
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index 8ce0b77..ca794d9 100644
--- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -4,7 +4,7 @@
 LL |     expect_sig(|a, b| b); // ought to return `a`
    |                ^^^^^^^^
    |
-   = note: defining type: DefId(0:4 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [
+   = note: defining type: test::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed('r)) i32,
            ]
@@ -27,7 +27,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:3 ~ return_wrong_bound_region[317d]::test[0]) with substs []
+   = note: defining type: test
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr
index 714a63b..69a6ab0 100644
--- a/src/test/ui/nll/issue-55394.stderr
+++ b/src/test/ui/nll/issue-55394.stderr
@@ -21,9 +21,13 @@
    |
 LL | impl Foo<'_> {
    |          ^^
-   = note: ...so that the expression is assignable:
-           expected Foo<'_>
-              found Foo<'_>
+note: ...so that the expression is assignable
+  --> $DIR/issue-55394.rs:9:9
+   |
+LL |         Foo { bar }
+   |         ^^^^^^^^^^^
+   = note: expected  `Foo<'_>`
+              found  `Foo<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr
index 3a152fb..58f2067 100644
--- a/src/test/ui/nll/normalization-bounds-error.stderr
+++ b/src/test/ui/nll/normalization-bounds-error.stderr
@@ -14,9 +14,13 @@
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
    |                  ^^
-   = note: ...so that the types are compatible:
-           expected Visitor<'d>
-              found Visitor<'_>
+note: ...so that the types are compatible
+  --> $DIR/normalization-bounds-error.rs:12:1
+   |
+LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected  `Visitor<'d>`
+              found  `Visitor<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/outlives-suggestion-simple.polonius.stderr b/src/test/ui/nll/outlives-suggestion-simple.polonius.stderr
new file mode 100644
index 0000000..8157446
--- /dev/null
+++ b/src/test/ui/nll/outlives-suggestion-simple.polonius.stderr
@@ -0,0 +1,121 @@
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:6:5
+   |
+LL | fn foo1<'a, 'b>(x: &'a usize) -> &'b usize {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:10:5
+   |
+LL | fn foo2<'a>(x: &'a usize) -> &'static usize {
+   |         -- lifetime `'a` defined here
+LL |     x
+   |     ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:14:5
+   |
+LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     (x, y)
+   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:14:5
+   |
+LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     (x, y)
+   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:22:5
+   |
+LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+...
+LL |     (x, x)
+   |     ^^^^^^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:22:5
+   |
+LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) {
+   |         --      -- lifetime `'c` defined here
+   |         |
+   |         lifetime `'a` defined here
+...
+LL |     (x, x)
+   |     ^^^^^^ returning this value requires that `'a` must outlive `'c`
+   |
+   = help: consider adding the following bound: `'a: 'c`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:31:9
+   |
+LL |     pub fn foo<'a>(x: &'a usize) -> Self {
+   |                -- lifetime `'a` defined here
+LL |         Foo { x }
+   |         ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:41:9
+   |
+LL | impl<'a> Bar<'a> {
+   |      -- lifetime `'a` defined here
+LL |     pub fn get<'b>(&self) -> &'b usize {
+   |                -- lifetime `'b` defined here
+LL |         self.x
+   |         ^^^^^^ returning this value requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/outlives-suggestion-simple.rs:52:9
+   |
+LL | impl<'a> Baz<'a> {
+   |      -- lifetime `'a` defined here
+LL |     fn get<'b>(&'b self) -> &'a i32 {
+   |            -- lifetime `'b` defined here
+LL |         self.x
+   |         ^^^^^^ returning this value requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/outlives-suggestion-simple.rs:73:9
+   |
+LL |     fn get_bar(&self) -> Bar2 {
+   |                -----
+   |                |
+   |                `self` is declared here, outside of the function body
+   |                `self` is a reference that is only valid in the function body
+LL |         Bar2::new(&self)
+   |         ^^^^^^^^^^^^^^^^ `self` escapes the function body here
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/nll/polonius/subset-relations.rs b/src/test/ui/nll/polonius/subset-relations.rs
new file mode 100644
index 0000000..3f6f67e
--- /dev/null
+++ b/src/test/ui/nll/polonius/subset-relations.rs
@@ -0,0 +1,30 @@
+// Checks that Polonius can compute cases of universal regions errors:
+// "illegal subset relation errors", cases where analysis finds that
+// two free regions outlive each other, without any evidence that this
+// relation holds.
+
+// ignore-compare-mode-nll
+// compile-flags: -Z borrowck=mir -Zpolonius
+
+// returning `y` requires that `'b: 'a`, but it's not known to be true
+fn missing_subset<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 {
+    y //~ ERROR
+}
+
+// `'b: 'a` is explicitly declared
+fn valid_subset<'a, 'b: 'a>(x: &'a u32, y: &'b u32) -> &'a u32 {
+    y
+}
+
+// because of `x`, it is implied that `'b: 'a` holds
+fn implied_bounds_subset<'a, 'b>(x: &'a &'b mut u32) -> &'a u32 {
+    x
+}
+
+// `'b: 'a` is declared, and `'a: 'c` is known via implied bounds:
+// `'b: 'c` is therefore known to hold transitively
+fn transitively_valid_subset<'a, 'b: 'a, 'c>(x: &'c &'a u32, y: &'b u32) -> &'c u32  {
+    y
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/polonius/subset-relations.stderr b/src/test/ui/nll/polonius/subset-relations.stderr
new file mode 100644
index 0000000..6364510
--- /dev/null
+++ b/src/test/ui/nll/polonius/subset-relations.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/subset-relations.rs:11:5
+   |
+LL | fn missing_subset<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 {
+   |                   --  -- lifetime `'b` defined here
+   |                   |
+   |                   lifetime `'a` defined here
+LL |     y
+   |     ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
index dd61023..c825227 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
@@ -4,9 +4,7 @@
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:13 ~ projection_no_regions_closure[317d]::no_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: no_region::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>,
            ]
@@ -25,10 +23,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:10 ~ projection_no_regions_closure[317d]::no_region[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: no_region::<'_#1r, T>
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
   --> $DIR/projection-no-regions-closure.rs:25:23
@@ -44,9 +39,7 @@
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:17 ~ projection_no_regions_closure[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: correct_region::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>,
            ]
@@ -64,10 +57,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:14 ~ projection_no_regions_closure[317d]::correct_region[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: correct_region::<'_#1r, T>
 
 note: External requirements
   --> $DIR/projection-no-regions-closure.rs:42:23
@@ -75,10 +65,7 @@
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:22 ~ projection_no_regions_closure[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: wrong_region::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>,
            ]
@@ -97,11 +84,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:18 ~ projection_no_regions_closure[317d]::wrong_region[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: wrong_region::<'_#1r, '_#2r, T>
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
   --> $DIR/projection-no-regions-closure.rs:42:23
@@ -117,10 +100,7 @@
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:27 ~ projection_no_regions_closure[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>,
            ]
@@ -139,11 +119,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:23 ~ projection_no_regions_closure[317d]::outlives_region[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: outlives_region::<'_#1r, '_#2r, T>
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index d9cbc71..7226c52 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -4,9 +4,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:19 ~ projection_one_region_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: no_relationships_late::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
@@ -27,10 +25,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:15 ~ projection_one_region_closure[317d]::no_relationships_late[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: no_relationships_late::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-one-region-closure.rs:45:29
@@ -59,10 +54,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:24 ~ projection_one_region_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -82,11 +74,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:20 ~ projection_one_region_closure[317d]::no_relationships_early[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-one-region-closure.rs:56:29
@@ -115,10 +103,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:29 ~ projection_one_region_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -137,11 +122,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:25 ~ projection_one_region_closure[317d]::projection_outlives[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: projection_outlives::<'_#1r, '_#2r, T>
 
 note: External requirements
   --> $DIR/projection-one-region-closure.rs:80:29
@@ -149,10 +130,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:34 ~ projection_one_region_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -172,11 +150,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:30 ~ projection_one_region_closure[317d]::elements_outlive[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: elements_outlive::<'_#1r, '_#2r, T>
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index 0be25de..655995c 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -4,9 +4,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:19 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: no_relationships_late::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
@@ -26,10 +24,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:15 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: no_relationships_late::<'_#1r, T>
 
 error: lifetime may not live long enough
   --> $DIR/projection-one-region-trait-bound-closure.rs:37:39
@@ -50,10 +45,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:24 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -72,11 +64,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:20 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
 
 error: lifetime may not live long enough
   --> $DIR/projection-one-region-trait-bound-closure.rs:47:39
@@ -97,10 +85,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:29 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -119,11 +104,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:25 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: projection_outlives::<'_#1r, '_#2r, T>
 
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:69:29
@@ -131,10 +112,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:34 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -153,11 +131,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:30 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: elements_outlive::<'_#1r, '_#2r, T>
 
 note: External requirements
   --> $DIR/projection-one-region-trait-bound-closure.rs:81:29
@@ -165,9 +139,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:38 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: one_region::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
@@ -186,10 +158,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:35 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: one_region::<'_#1r, T>
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
index 9cc2e50..2fb07b9 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
@@ -4,9 +4,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:19 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: no_relationships_late::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
@@ -23,10 +21,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:15 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: no_relationships_late::<'_#1r, T>
 
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:45:29
@@ -34,10 +29,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:24 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -54,11 +46,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:20 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
 
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:64:29
@@ -66,10 +54,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:29 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -86,11 +71,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:25 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: projection_outlives::<'_#1r, '_#2r, T>
 
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:73:29
@@ -98,10 +79,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:34 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -118,11 +96,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:30 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: elements_outlive::<'_#1r, '_#2r, T>
 
 note: No external requirements
   --> $DIR/projection-one-region-trait-bound-static-closure.rs:85:29
@@ -130,9 +104,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:38 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: one_region::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
@@ -149,8 +121,5 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:35 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: one_region::<'_#1r, T>
 
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index ed53ce9..501a55e3 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -4,10 +4,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:22 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -27,11 +24,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:17 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>
 
 error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
   --> $DIR/projection-two-region-trait-bound-closure.rs:38:29
@@ -47,11 +40,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:28 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
+   = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
            ]
@@ -70,12 +59,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:23 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
-           ]
+   = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>
 
 error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
   --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
@@ -91,11 +75,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:34 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
+   = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
            ]
@@ -114,12 +94,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:29 ~ projection_two_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
-           ]
+   = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>
 
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:70:29
@@ -127,11 +102,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:40 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
+   = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
            ]
@@ -150,12 +121,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:35 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive1[0]) with substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
-           ]
+   = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>
 
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:79:29
@@ -163,11 +129,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:46 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
+   = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
            ]
@@ -186,12 +148,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:41 ~ projection_two_region_trait_bound_closure[317d]::elements_outlive2[0]) with substs [
-               '_#1r,
-               '_#2r,
-               '_#3r,
-               T,
-           ]
+   = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>
 
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:87:29
@@ -199,9 +156,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:51 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: two_regions::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
@@ -221,10 +176,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:47 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: two_regions::<'_#1r, T>
 
 error: lifetime may not live long enough
   --> $DIR/projection-two-region-trait-bound-closure.rs:87:29
@@ -245,10 +197,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:56 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -267,11 +216,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:52 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>
 
 note: External requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:109:29
@@ -279,9 +224,7 @@
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:60 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: one_region::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
@@ -300,10 +243,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:57 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: one_region::<'_#1r, T>
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index e2a9bd7..db0bca1 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -4,8 +4,7 @@
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:11 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]::{{closure}}[0]) with closure substs [
-               T,
+   = note: defining type: generic::<T>::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed('s)) T)),
            ]
@@ -21,9 +20,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:9 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]) with substs [
-               T,
-           ]
+   = note: defining type: generic::<T>
 
 note: External requirements
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
@@ -31,8 +28,7 @@
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
    |
-   = note: defining type: DefId(0:15 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [
-               T,
+   = note: defining type: generic_fail::<T>::{{closure}}#0 with closure substs [
                i16,
                for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed('s)) T)),
            ]
@@ -49,9 +45,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:12 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]) with substs [
-               T,
-           ]
+   = note: defining type: generic_fail::<T>
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
index 7c8dc94..0021d73 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -4,9 +4,7 @@
 LL |     with_signature(x, |y| y)
    |                       ^^^^^
    |
-   = note: defining type: DefId(0:11 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: no_region::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>,
            ]
@@ -25,10 +23,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:8 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: no_region::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
index ffd936b..46fef8e 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -11,8 +11,7 @@
 LL | |     })
    | |_____^
    |
-   = note: defining type: DefId(0:14 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]::{{closure}}[0]) with closure substs [
-               T,
+   = note: defining type: no_region::<T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T)),
            ]
@@ -32,9 +31,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:11 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]) with substs [
-               T,
-           ]
+   = note: defining type: no_region::<T>
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
@@ -64,9 +61,7 @@
 LL | |     })
    | |_____^
    |
-   = note: defining type: DefId(0:18 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: correct_region::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
@@ -85,10 +80,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:15 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: correct_region::<'_#1r, T>
 
 note: External requirements
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
@@ -101,9 +93,7 @@
 LL | |     })
    | |_____^
    |
-   = note: defining type: DefId(0:23 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               T,
+   = note: defining type: wrong_region::<'_#1r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
@@ -123,10 +113,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:19 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]) with substs [
-               '_#1r,
-               T,
-           ]
+   = note: defining type: wrong_region::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
@@ -151,10 +138,7 @@
 LL | |     })
    | |_____^
    |
-   = note: defining type: DefId(0:28 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]::{{closure}}[0]) with closure substs [
-               '_#1r,
-               '_#2r,
-               T,
+   = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{{closure}}#0 with closure substs [
                i32,
                extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
@@ -173,11 +157,7 @@
 LL | | }
    | |_^
    |
-   = note: defining type: DefId(0:24 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]) with substs [
-               '_#1r,
-               '_#2r,
-               T,
-           ]
+   = note: defining type: outlives_region::<'_#1r, '_#2r, T>
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr
index 6986389..5191dec 100644
--- a/src/test/ui/nll/type-alias-free-regions.stderr
+++ b/src/test/ui/nll/type-alias-free-regions.stderr
@@ -11,17 +11,25 @@
 LL | |         C { f: b }
 LL | |     }
    | |_____^
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<std::boxed::Box<&isize>>
-              found std::boxed::Box<std::boxed::Box<&isize>>
+note: ...so that the expression is assignable
+  --> $DIR/type-alias-free-regions.rs:17:16
+   |
+LL |         C { f: b }
+   |                ^
+   = note: expected  `std::boxed::Box<std::boxed::Box<&isize>>`
+              found  `std::boxed::Box<std::boxed::Box<&isize>>`
 note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
   --> $DIR/type-alias-free-regions.rs:15:6
    |
 LL | impl<'a> FromBox<'a> for C<'a> {
    |      ^^
-   = note: ...so that the expression is assignable:
-           expected C<'a>
-              found C<'_>
+note: ...so that the expression is assignable
+  --> $DIR/type-alias-free-regions.rs:17:9
+   |
+LL |         C { f: b }
+   |         ^^^^^^^^^^
+   = note: expected  `C<'a>`
+              found  `C<'_>`
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/type-alias-free-regions.rs:27:16
@@ -36,17 +44,25 @@
 LL | |         C { f: Box::new(b.0) }
 LL | |     }
    | |_____^
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<&isize>
-              found std::boxed::Box<&isize>
+note: ...so that the expression is assignable
+  --> $DIR/type-alias-free-regions.rs:27:25
+   |
+LL |         C { f: Box::new(b.0) }
+   |                         ^^^
+   = note: expected  `std::boxed::Box<&isize>`
+              found  `std::boxed::Box<&isize>`
 note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 25:6...
   --> $DIR/type-alias-free-regions.rs:25:6
    |
 LL | impl<'a> FromTuple<'a> for C<'a> {
    |      ^^
-   = note: ...so that the expression is assignable:
-           expected C<'a>
-              found C<'_>
+note: ...so that the expression is assignable
+  --> $DIR/type-alias-free-regions.rs:27:9
+   |
+LL |         C { f: Box::new(b.0) }
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected  `C<'a>`
+              found  `C<'_>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/user-annotations/closure-substs.polonius.stderr b/src/test/ui/nll/user-annotations/closure-substs.polonius.stderr
new file mode 100644
index 0000000..d5bcdf6
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/closure-substs.polonius.stderr
@@ -0,0 +1,60 @@
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:8:16
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |         return x;
+   |                ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:15:16
+   |
+LL |     |x: &i32| -> &'static i32 {
+   |         - let's call the lifetime of this reference `'1`
+LL |         return x;
+   |                ^ returning this value requires that `'1` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:15:16
+   |
+LL |     |x: &i32| -> &'static i32 {
+   |         -        ------------ return type of closure is &'2 i32
+   |         |
+   |         let's call the lifetime of this reference `'1`
+LL |         return x;
+   |                ^ returning this value requires that `'1` must outlive `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/closure-substs.rs:22:9
+   |
+LL | fn bar<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |         b(x);
+   |         ^^^^ argument requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/closure-substs.rs:29:9
+   |
+LL |     |x: &i32, b: fn(&'static i32)| {
+   |      - `x` is a reference that is only valid in the closure body
+LL |         b(x);
+   |         ^^^^ `x` escapes the closure body here
+
+error[E0521]: borrowed data escapes outside of closure
+  --> $DIR/closure-substs.rs:29:9
+   |
+LL |     |x: &i32, b: fn(&'static i32)| {
+   |      -        - `b` is declared here, outside of the closure body
+   |      |
+   |      `x` is a reference that is only valid in the closure body
+LL |         b(x);
+   |         ^^^^ `x` escapes the closure body here
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
index 4ebd991..37be450 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
@@ -9,9 +9,13 @@
    |
 LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
    |        ^^
-   = note: ...so that the types are compatible:
-           expected Foo<'_>
-              found Foo<'a>
+note: ...so that the types are compatible
+  --> $DIR/constant-in-expr-inherent-1.rs:8:5
+   |
+LL |     <Foo<'a>>::C
+   |     ^^^^^^^^^^^^
+   = note: expected  `Foo<'_>`
+              found  `Foo<'a>`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that reference does not outlive borrowed content
   --> $DIR/constant-in-expr-inherent-1.rs:8:5
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
index d61659e..4ee3284 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
@@ -9,9 +9,13 @@
    |
 LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
    |        ^^
-   = note: ...so that the types are compatible:
-           expected Foo<'_>
-              found Foo<'a>
+note: ...so that the types are compatible
+  --> $DIR/constant-in-expr-trait-item-3.rs:10:5
+   |
+LL |     T::C
+   |     ^^^^
+   = note: expected  `Foo<'_>`
+              found  `Foo<'a>`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that reference does not outlive borrowed content
   --> $DIR/constant-in-expr-trait-item-3.rs:10:5
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
index d66322c..1952ee8 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
@@ -19,9 +19,13 @@
    |
 LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
    |             ^^
-   = note: ...so that the expression is assignable:
-           expected &'b (dyn SomeTrait + 'b)
-              found &dyn SomeTrait
+note: ...so that the expression is assignable
+  --> $DIR/object-lifetime-default-elision.rs:71:5
+   |
+LL |     ss
+   |     ^^
+   = note: expected  `&'b (dyn SomeTrait + 'b)`
+              found  `&dyn SomeTrait`
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/object-lifetime-default-elision.rs:71:5
@@ -44,9 +48,13 @@
    |
 LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
    |             ^^
-   = note: ...so that the expression is assignable:
-           expected &'b (dyn SomeTrait + 'b)
-              found &dyn SomeTrait
+note: ...so that the expression is assignable
+  --> $DIR/object-lifetime-default-elision.rs:71:5
+   |
+LL |     ss
+   |     ^^
+   = note: expected  `&'b (dyn SomeTrait + 'b)`
+              found  `&dyn SomeTrait`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.rs b/src/test/ui/on-unimplemented/expected-comma-found-token.rs
index 77c0ea1..8fb34f2 100644
--- a/src/test/ui/on-unimplemented/expected-comma-found-token.rs
+++ b/src/test/ui/on-unimplemented/expected-comma-found-token.rs
@@ -6,7 +6,7 @@
 
 #[rustc_on_unimplemented(
     message="the message"
-    label="the label" //~ ERROR expected one of `)` or `,`, found `label`
+    label="the label" //~ ERROR expected `,`, found `label`
 )]
 trait T {}
 
diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.stderr b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
index 2e1d484..048b72e 100644
--- a/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
+++ b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
@@ -1,11 +1,8 @@
-error: expected one of `)` or `,`, found `label`
+error: expected `,`, found `label`
   --> $DIR/expected-comma-found-token.rs:9:5
    |
 LL |     message="the message"
-   |                          -
-   |                          |
-   |                          expected one of `)` or `,`
-   |                          help: missing `,`
+   |                          - expected `,`
 LL |     label="the label"
    |     ^^^^^ unexpected token
 
diff --git a/src/test/ui/parser/lifetime-in-pattern-recover.rs b/src/test/ui/parser/lifetime-in-pattern-recover.rs
new file mode 100644
index 0000000..7fb14b8
--- /dev/null
+++ b/src/test/ui/parser/lifetime-in-pattern-recover.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let &'a x = &0; //~ ERROR unexpected lifetime `'a` in pattern
+    let &'a mut y = &mut 0; //~ ERROR unexpected lifetime `'a` in pattern
+
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/lifetime-in-pattern-recover.stderr b/src/test/ui/parser/lifetime-in-pattern-recover.stderr
new file mode 100644
index 0000000..4bf7f57
--- /dev/null
+++ b/src/test/ui/parser/lifetime-in-pattern-recover.stderr
@@ -0,0 +1,23 @@
+error: unexpected lifetime `'a` in pattern
+  --> $DIR/lifetime-in-pattern-recover.rs:2:10
+   |
+LL |     let &'a x = &0;
+   |          ^^ help: remove the lifetime
+
+error: unexpected lifetime `'a` in pattern
+  --> $DIR/lifetime-in-pattern-recover.rs:3:10
+   |
+LL |     let &'a mut y = &mut 0;
+   |          ^^ help: remove the lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/lifetime-in-pattern-recover.rs:5:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/lifetime-in-pattern.rs b/src/test/ui/parser/lifetime-in-pattern.rs
index afee685..d3c638d 100644
--- a/src/test/ui/parser/lifetime-in-pattern.rs
+++ b/src/test/ui/parser/lifetime-in-pattern.rs
@@ -1,5 +1,6 @@
 fn test(&'a str) {
     //~^ ERROR unexpected lifetime `'a` in pattern
+    //~| ERROR expected one of `:`, `@`, or `|`, found `)`
 }
 
 fn main() {
diff --git a/src/test/ui/parser/lifetime-in-pattern.stderr b/src/test/ui/parser/lifetime-in-pattern.stderr
index e525c7b..71fd3cd 100644
--- a/src/test/ui/parser/lifetime-in-pattern.stderr
+++ b/src/test/ui/parser/lifetime-in-pattern.stderr
@@ -2,7 +2,13 @@
   --> $DIR/lifetime-in-pattern.rs:1:10
    |
 LL | fn test(&'a str) {
-   |          ^^ unexpected lifetime
+   |          ^^ help: remove the lifetime
 
-error: aborting due to previous error
+error: expected one of `:`, `@`, or `|`, found `)`
+  --> $DIR/lifetime-in-pattern.rs:1:16
+   |
+LL | fn test(&'a str) {
+   |                ^ expected one of `:`, `@`, or `|`
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/raw/raw-literal-keywords.rs b/src/test/ui/parser/raw/raw-literal-keywords.rs
index bf9cbcd..a986980 100644
--- a/src/test/ui/parser/raw/raw-literal-keywords.rs
+++ b/src/test/ui/parser/raw/raw-literal-keywords.rs
@@ -11,11 +11,11 @@
 }
 
 fn test_if_2() {
-    let _ = r#if; //~ ERROR cannot find value `if` in this scope
+    let _ = r#if; //~ ERROR cannot find value `r#if` in this scope
 }
 
 fn test_struct_2() {
-    let _ = r#struct; //~ ERROR cannot find value `struct` in this scope
+    let _ = r#struct; //~ ERROR cannot find value `r#struct` in this scope
 }
 
 fn test_union_2() {
diff --git a/src/test/ui/parser/raw/raw-literal-keywords.stderr b/src/test/ui/parser/raw/raw-literal-keywords.stderr
index fd8eda3..f7b6c89 100644
--- a/src/test/ui/parser/raw/raw-literal-keywords.stderr
+++ b/src/test/ui/parser/raw/raw-literal-keywords.stderr
@@ -16,13 +16,13 @@
 LL |     r#union Test;
    |             ^^^^ expected one of 8 possible tokens
 
-error[E0425]: cannot find value `if` in this scope
+error[E0425]: cannot find value `r#if` in this scope
   --> $DIR/raw-literal-keywords.rs:14:13
    |
 LL |     let _ = r#if;
    |             ^^^^ not found in this scope
 
-error[E0425]: cannot find value `struct` in this scope
+error[E0425]: cannot find value `r#struct` in this scope
   --> $DIR/raw-literal-keywords.rs:18:13
    |
 LL |     let _ = r#struct;
diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
index 792ab6f..1b1096c 100644
--- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
+++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
@@ -9,8 +9,13 @@
 error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
   --> $DIR/always-inhabited-union-ref.rs:27:11
    |
-LL |     match uninhab_union() {
-   |           ^^^^^^^^^^^^^^^
+LL | / pub union Foo {
+LL | |     foo: !,
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match uninhab_union() {
+   |             ^^^^^^^^^^^^^^^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs
new file mode 100644
index 0000000..57b6b91
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs
@@ -0,0 +1,93 @@
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+#![deny(unreachable_patterns)]
+enum Foo {}
+
+struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here
+union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here
+    foo: (),
+}
+union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here
+    foo: (),
+    bar: (),
+}
+enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here
+    Foo(bool),
+    //~^ not covered
+    //~| not covered
+}
+enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here
+    Foo(bool),
+    //~^ not covered
+    //~| not covered
+    Bar,
+    //~^ not covered
+    //~| not covered
+}
+enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here
+    V1, V2, V3, V4, V5,
+}
+
+macro_rules! match_empty {
+    ($e:expr) => {
+        match $e {}
+    };
+}
+macro_rules! match_false {
+    ($e:expr) => {
+        match $e {
+            _ if false => {}
+        }
+    };
+}
+
+fn foo(x: Foo) {
+    match_empty!(x); // ok
+    match x {
+        _ => {}, //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {}, //~ ERROR unreachable pattern
+    }
+}
+
+fn main() {
+    match None::<!> {
+        None => {}
+        Some(_) => {} //~ ERROR unreachable pattern
+    }
+    match None::<Foo> {
+        None => {}
+        Some(_) => {} //~ ERROR unreachable pattern
+    }
+
+    match_empty!(0u8);
+    //~^ ERROR type `u8` is non-empty
+    match_empty!(NonEmptyStruct(true));
+    //~^ ERROR type `NonEmptyStruct` is non-empty
+    match_empty!((NonEmptyUnion1 { foo: () }));
+    //~^ ERROR type `NonEmptyUnion1` is non-empty
+    match_empty!((NonEmptyUnion2 { foo: () }));
+    //~^ ERROR type `NonEmptyUnion2` is non-empty
+    match_empty!(NonEmptyEnum1::Foo(true));
+    //~^ ERROR `Foo(_)` not covered
+    match_empty!(NonEmptyEnum2::Foo(true));
+    //~^ ERROR `Foo(_)` and `Bar` not covered
+    match_empty!(NonEmptyEnum5::V1);
+    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+
+    match_false!(0u8);
+    //~^ ERROR `_` not covered
+    match_false!(NonEmptyStruct(true));
+    //~^ ERROR `NonEmptyStruct(_)` not covered
+    match_false!((NonEmptyUnion1 { foo: () }));
+    //~^ ERROR `NonEmptyUnion1 { .. }` not covered
+    match_false!((NonEmptyUnion2 { foo: () }));
+    //~^ ERROR `NonEmptyUnion2 { .. }` not covered
+    match_false!(NonEmptyEnum1::Foo(true));
+    //~^ ERROR `Foo(_)` not covered
+    match_false!(NonEmptyEnum2::Foo(true));
+    //~^ ERROR `Foo(_)` and `Bar` not covered
+    match_false!(NonEmptyEnum5::V1);
+    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+}
diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr
new file mode 100644
index 0000000..f242ecf
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr
@@ -0,0 +1,223 @@
+error: unreachable pattern
+  --> $DIR/match-empty-exhaustive_patterns.rs:47:9
+   |
+LL |         _ => {},
+   |         ^
+   |
+note: lint level defined here
+  --> $DIR/match-empty-exhaustive_patterns.rs:3:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-empty-exhaustive_patterns.rs:50:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/match-empty-exhaustive_patterns.rs:57:9
+   |
+LL |         Some(_) => {}
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-empty-exhaustive_patterns.rs:61:9
+   |
+LL |         Some(_) => {}
+   |         ^^^^^^^
+
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+  --> $DIR/match-empty-exhaustive_patterns.rs:64:18
+   |
+LL |     match_empty!(0u8);
+   |                  ^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty
+  --> $DIR/match-empty-exhaustive_patterns.rs:66:18
+   |
+LL | struct NonEmptyStruct(bool);
+   | ---------------------------- `NonEmptyStruct` defined here
+...
+LL |     match_empty!(NonEmptyStruct(true));
+   |                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
+  --> $DIR/match-empty-exhaustive_patterns.rs:68:18
+   |
+LL | / union NonEmptyUnion1 {
+LL | |     foo: (),
+LL | | }
+   | |_- `NonEmptyUnion1` defined here
+...
+LL |       match_empty!((NonEmptyUnion1 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
+  --> $DIR/match-empty-exhaustive_patterns.rs:70:18
+   |
+LL | / union NonEmptyUnion2 {
+LL | |     foo: (),
+LL | |     bar: (),
+LL | | }
+   | |_- `NonEmptyUnion2` defined here
+...
+LL |       match_empty!((NonEmptyUnion2 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:72:18
+   |
+LL | / enum NonEmptyEnum1 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |
+LL | |
+LL | | }
+   | |_- `NonEmptyEnum1` defined here
+...
+LL |       match_empty!(NonEmptyEnum1::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:74:18
+   |
+LL | / enum NonEmptyEnum2 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |
+LL | |
+LL | |     Bar,
+   | |     --- not covered
+LL | |
+LL | |
+LL | | }
+   | |_- `NonEmptyEnum2` defined here
+...
+LL |       match_empty!(NonEmptyEnum2::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:76:18
+   |
+LL | / enum NonEmptyEnum5 {
+LL | |     V1, V2, V3, V4, V5,
+LL | | }
+   | |_- `NonEmptyEnum5` defined here
+...
+LL |       match_empty!(NonEmptyEnum5::V1);
+   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:79:18
+   |
+LL |     match_false!(0u8);
+   |                  ^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:81:18
+   |
+LL | struct NonEmptyStruct(bool);
+   | ---------------------------- `NonEmptyStruct` defined here
+...
+LL |     match_false!(NonEmptyStruct(true));
+   |                  ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:83:18
+   |
+LL | / union NonEmptyUnion1 {
+LL | |     foo: (),
+LL | | }
+   | |_- `NonEmptyUnion1` defined here
+...
+LL |       match_false!((NonEmptyUnion1 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:85:18
+   |
+LL | / union NonEmptyUnion2 {
+LL | |     foo: (),
+LL | |     bar: (),
+LL | | }
+   | |_- `NonEmptyUnion2` defined here
+...
+LL |       match_false!((NonEmptyUnion2 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:87:18
+   |
+LL | / enum NonEmptyEnum1 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |
+LL | |
+LL | | }
+   | |_- `NonEmptyEnum1` defined here
+...
+LL |       match_false!(NonEmptyEnum1::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:89:18
+   |
+LL | / enum NonEmptyEnum2 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |
+LL | |
+LL | |     Bar,
+   | |     --- not covered
+LL | |
+LL | |
+LL | | }
+   | |_- `NonEmptyEnum2` defined here
+...
+LL |       match_false!(NonEmptyEnum2::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+  --> $DIR/match-empty-exhaustive_patterns.rs:91:18
+   |
+LL | / enum NonEmptyEnum5 {
+LL | |     V1, V2, V3, V4, V5,
+LL | | }
+   | |_- `NonEmptyEnum5` defined here
+...
+LL |       match_false!(NonEmptyEnum5::V1);
+   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/match-empty.rs b/src/test/ui/pattern/usefulness/match-empty.rs
new file mode 100644
index 0000000..f757712
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-empty.rs
@@ -0,0 +1,92 @@
+#![feature(never_type)]
+#![deny(unreachable_patterns)]
+enum Foo {}
+
+struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here
+union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here
+    foo: (),
+}
+union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here
+    foo: (),
+    bar: (),
+}
+enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here
+    Foo(bool),
+    //~^ not covered
+    //~| not covered
+}
+enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here
+    Foo(bool),
+    //~^ not covered
+    //~| not covered
+    Bar,
+    //~^ not covered
+    //~| not covered
+}
+enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here
+    V1, V2, V3, V4, V5,
+}
+
+macro_rules! match_empty {
+    ($e:expr) => {
+        match $e {}
+    };
+}
+macro_rules! match_false {
+    ($e:expr) => {
+        match $e {
+            _ if false => {}
+        }
+    };
+}
+
+fn foo(x: Foo) {
+    match_empty!(x); // ok
+    match_false!(x); // Not detected as unreachable nor exhaustive.
+    //~^ ERROR non-exhaustive patterns: `_` not covered
+    match x {
+        _ => {}, // Not detected as unreachable, see #55123.
+    }
+}
+
+fn main() {
+    // `exhaustive_patterns` is not on, so uninhabited branches are not detected as unreachable.
+    match None::<!> {
+        None => {}
+        Some(_) => {}
+    }
+    match None::<Foo> {
+        None => {}
+        Some(_) => {}
+    }
+
+    match_empty!(0u8);
+    //~^ ERROR type `u8` is non-empty
+    match_empty!(NonEmptyStruct(true));
+    //~^ ERROR type `NonEmptyStruct` is non-empty
+    match_empty!((NonEmptyUnion1 { foo: () }));
+    //~^ ERROR type `NonEmptyUnion1` is non-empty
+    match_empty!((NonEmptyUnion2 { foo: () }));
+    //~^ ERROR type `NonEmptyUnion2` is non-empty
+    match_empty!(NonEmptyEnum1::Foo(true));
+    //~^ ERROR `Foo(_)` not covered
+    match_empty!(NonEmptyEnum2::Foo(true));
+    //~^ ERROR `Foo(_)` and `Bar` not covered
+    match_empty!(NonEmptyEnum5::V1);
+    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+
+    match_false!(0u8);
+    //~^ ERROR `_` not covered
+    match_false!(NonEmptyStruct(true));
+    //~^ ERROR `NonEmptyStruct(_)` not covered
+    match_false!((NonEmptyUnion1 { foo: () }));
+    //~^ ERROR `NonEmptyUnion1 { .. }` not covered
+    match_false!((NonEmptyUnion2 { foo: () }));
+    //~^ ERROR `NonEmptyUnion2 { .. }` not covered
+    match_false!(NonEmptyEnum1::Foo(true));
+    //~^ ERROR `Foo(_)` not covered
+    match_false!(NonEmptyEnum2::Foo(true));
+    //~^ ERROR `Foo(_)` and `Bar` not covered
+    match_false!(NonEmptyEnum5::V1);
+    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+}
diff --git a/src/test/ui/pattern/usefulness/match-empty.stderr b/src/test/ui/pattern/usefulness/match-empty.stderr
new file mode 100644
index 0000000..72e3fc0
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-empty.stderr
@@ -0,0 +1,204 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/match-empty.rs:45:18
+   |
+LL | enum Foo {}
+   | ----------- `Foo` defined here
+...
+LL |     match_false!(x); // Not detected as unreachable nor exhaustive.
+   |                  ^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+  --> $DIR/match-empty.rs:63:18
+   |
+LL |     match_empty!(0u8);
+   |                  ^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty
+  --> $DIR/match-empty.rs:65:18
+   |
+LL | struct NonEmptyStruct(bool);
+   | ---------------------------- `NonEmptyStruct` defined here
+...
+LL |     match_empty!(NonEmptyStruct(true));
+   |                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
+  --> $DIR/match-empty.rs:67:18
+   |
+LL | / union NonEmptyUnion1 {
+LL | |     foo: (),
+LL | | }
+   | |_- `NonEmptyUnion1` defined here
+...
+LL |       match_empty!((NonEmptyUnion1 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
+  --> $DIR/match-empty.rs:69:18
+   |
+LL | / union NonEmptyUnion2 {
+LL | |     foo: (),
+LL | |     bar: (),
+LL | | }
+   | |_- `NonEmptyUnion2` defined here
+...
+LL |       match_empty!((NonEmptyUnion2 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+  --> $DIR/match-empty.rs:71:18
+   |
+LL | / enum NonEmptyEnum1 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |
+LL | |
+LL | | }
+   | |_- `NonEmptyEnum1` defined here
+...
+LL |       match_empty!(NonEmptyEnum1::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+  --> $DIR/match-empty.rs:73:18
+   |
+LL | / enum NonEmptyEnum2 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |
+LL | |
+LL | |     Bar,
+   | |     --- not covered
+LL | |
+LL | |
+LL | | }
+   | |_- `NonEmptyEnum2` defined here
+...
+LL |       match_empty!(NonEmptyEnum2::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+  --> $DIR/match-empty.rs:75:18
+   |
+LL | / enum NonEmptyEnum5 {
+LL | |     V1, V2, V3, V4, V5,
+LL | | }
+   | |_- `NonEmptyEnum5` defined here
+...
+LL |       match_empty!(NonEmptyEnum5::V1);
+   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/match-empty.rs:78:18
+   |
+LL |     match_false!(0u8);
+   |                  ^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
+  --> $DIR/match-empty.rs:80:18
+   |
+LL | struct NonEmptyStruct(bool);
+   | ---------------------------- `NonEmptyStruct` defined here
+...
+LL |     match_false!(NonEmptyStruct(true));
+   |                  ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
+  --> $DIR/match-empty.rs:82:18
+   |
+LL | / union NonEmptyUnion1 {
+LL | |     foo: (),
+LL | | }
+   | |_- `NonEmptyUnion1` defined here
+...
+LL |       match_false!((NonEmptyUnion1 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
+  --> $DIR/match-empty.rs:84:18
+   |
+LL | / union NonEmptyUnion2 {
+LL | |     foo: (),
+LL | |     bar: (),
+LL | | }
+   | |_- `NonEmptyUnion2` defined here
+...
+LL |       match_false!((NonEmptyUnion2 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
+  --> $DIR/match-empty.rs:86:18
+   |
+LL | / enum NonEmptyEnum1 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |
+LL | |
+LL | | }
+   | |_- `NonEmptyEnum1` defined here
+...
+LL |       match_false!(NonEmptyEnum1::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
+  --> $DIR/match-empty.rs:88:18
+   |
+LL | / enum NonEmptyEnum2 {
+LL | |     Foo(bool),
+   | |     --- not covered
+LL | |
+LL | |
+LL | |     Bar,
+   | |     --- not covered
+LL | |
+LL | |
+LL | | }
+   | |_- `NonEmptyEnum2` defined here
+...
+LL |       match_false!(NonEmptyEnum2::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
+  --> $DIR/match-empty.rs:90:18
+   |
+LL | / enum NonEmptyEnum5 {
+LL | |     V1, V2, V3, V4, V5,
+LL | | }
+   | |_- `NonEmptyEnum5` defined here
+...
+LL |       match_false!(NonEmptyEnum5::V1);
+   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 15 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/print_type_sizes/zero-sized-fields.rs b/src/test/ui/print_type_sizes/zero-sized-fields.rs
new file mode 100644
index 0000000..2ad488e
--- /dev/null
+++ b/src/test/ui/print_type_sizes/zero-sized-fields.rs
@@ -0,0 +1,46 @@
+// compile-flags: -Z print-type-sizes
+// build-pass (FIXME(62277): could be check-pass?)
+
+// At one point, zero-sized fields such as those in this file were causing
+// incorrect output from `-Z print-type-sizes`.
+
+#![feature(start)]
+
+struct S1 {
+    x: u32,
+    y: u32,
+    tag: (),
+}
+
+struct Void();
+struct Empty {}
+
+struct S5<TagW, TagZ> {
+    tagw: TagW,
+    w: u32,
+    unit: (),
+    x: u32,
+    void: Void,
+    y: u32,
+    empty: Empty,
+    z: u32,
+    tagz: TagZ,
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _s1: S1 = S1 { x: 0, y: 0, tag: () };
+
+    let _s5: S5<(), Empty> = S5 {
+        tagw: (),
+        w: 1,
+        unit: (),
+        x: 2,
+        void: Void(),
+        y: 3,
+        empty: Empty {},
+        z: 4,
+        tagz: Empty {},
+    };
+    0
+}
diff --git a/src/test/ui/print_type_sizes/zero-sized-fields.stdout b/src/test/ui/print_type_sizes/zero-sized-fields.stdout
new file mode 100644
index 0000000..72f59c4
--- /dev/null
+++ b/src/test/ui/print_type_sizes/zero-sized-fields.stdout
@@ -0,0 +1,16 @@
+print-type-size type: `S5<(), Empty>`: 16 bytes, alignment: 4 bytes
+print-type-size     field `.tagw`: 0 bytes
+print-type-size     field `.unit`: 0 bytes
+print-type-size     field `.void`: 0 bytes
+print-type-size     field `.empty`: 0 bytes
+print-type-size     field `.tagz`: 0 bytes
+print-type-size     field `.w`: 4 bytes
+print-type-size     field `.x`: 4 bytes
+print-type-size     field `.y`: 4 bytes
+print-type-size     field `.z`: 4 bytes
+print-type-size type: `S1`: 8 bytes, alignment: 4 bytes
+print-type-size     field `.tag`: 0 bytes
+print-type-size     field `.x`: 4 bytes
+print-type-size     field `.y`: 4 bytes
+print-type-size type: `Empty`: 0 bytes, alignment: 1 bytes
+print-type-size type: `Void`: 0 bytes, alignment: 1 bytes
diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
index 7846153..feab72b 100644
--- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
+++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
@@ -1,11 +1,10 @@
- // aux-build:priv_dep.rs
+ // aux-crate:priv:priv_dep=priv_dep.rs
  // aux-build:pub_dep.rs
- // extern-private:priv_dep
 #![deny(exported_private_dependencies)]
 
 // This crate is a private dependency
 extern crate priv_dep;
-// This crate is a public dependenct
+// This crate is a public dependency
 extern crate pub_dep;
 
 use priv_dep::{OtherType, OtherTrait};
diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
index b31efdb..f21b11f 100644
--- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
+++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
@@ -1,23 +1,23 @@
 error: type `priv_dep::OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:21:5
+  --> $DIR/pub-priv1.rs:20:5
    |
 LL |     pub field: OtherType,
    |     ^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/pub-priv1.rs:4:9
+  --> $DIR/pub-priv1.rs:3:9
    |
 LL | #![deny(exported_private_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `priv_dep::OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:28:5
+  --> $DIR/pub-priv1.rs:27:5
    |
 LL |     pub fn pub_fn(param: OtherType) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait `priv_dep::OtherTrait` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:34:1
+  --> $DIR/pub-priv1.rs:33:1
    |
 LL | / pub trait MyPubTrait {
 LL | |     type Foo: OtherTrait;
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index cd6f0ea..a77e920 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -14,6 +14,11 @@
 LL |     match x {
 LL |         Some(x) => { return x },
    |                             ^ expected `usize`, found `isize`
+   |
+help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         Some(x) => { return x.try_into().unwrap() },
+   |                             ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:33:22
diff --git a/src/test/ui/question-mark-type-infer.rs b/src/test/ui/question-mark-type-infer.rs
index 95ee01a..2ef8618 100644
--- a/src/test/ui/question-mark-type-infer.rs
+++ b/src/test/ui/question-mark-type-infer.rs
@@ -9,7 +9,7 @@
 
 fn g() -> Result<Vec<i32>, ()> {
     let l = [1, 2, 3, 4];
-    l.iter().map(f).collect()? //~ ERROR type annotations needed: cannot resolve
+    l.iter().map(f).collect()? //~ ERROR type annotations needed
 }
 
 fn main() {
diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr
index 53a170e..7911701 100644
--- a/src/test/ui/question-mark-type-infer.stderr
+++ b/src/test/ui/question-mark-type-infer.stderr
@@ -1,8 +1,13 @@
-error[E0284]: type annotations needed: cannot resolve `<_ as std::ops::Try>::Ok == _`
-  --> $DIR/question-mark-type-infer.rs:12:5
+error[E0284]: type annotations needed
+  --> $DIR/question-mark-type-infer.rs:12:21
    |
 LL |     l.iter().map(f).collect()?
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^^^^^^
+   |                     |
+   |                     cannot infer type
+   |                     help: consider specifying the type argument in the method call: `collect::<B>`
+   |
+   = note: cannot resolve `<_ as std::ops::Try>::Ok == _`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
index 14934d6..e889651 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -34,17 +34,25 @@
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |      ^^
-   = note: ...so that the expression is assignable:
-           expected &[u8]
-              found &'a [u8]
+note: ...so that the expression is assignable
+  --> $DIR/region-object-lifetime-in-coercion.rs:26:14
+   |
+LL |     Box::new(v)
+   |              ^
+   = note: expected  `&[u8]`
+              found  `&'a [u8]`
 note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 25:9...
   --> $DIR/region-object-lifetime-in-coercion.rs:25:9
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |         ^^
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn Foo + 'b)>
-              found std::boxed::Box<dyn Foo>
+note: ...so that the expression is assignable
+  --> $DIR/region-object-lifetime-in-coercion.rs:26:5
+   |
+LL |     Box::new(v)
+   |     ^^^^^^^^^^^
+   = note: expected  `std::boxed::Box<(dyn Foo + 'b)>`
+              found  `std::boxed::Box<dyn Foo>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
index a636c9e..865e967 100644
--- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
+++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
@@ -9,9 +9,13 @@
    |
 LL | impl<'a> Foo<'static> for &'a i32 {
    |      ^^
-   = note: ...so that the types are compatible:
-           expected Foo<'static>
-              found Foo<'static>
+note: ...so that the types are compatible
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
+   |
+LL | impl<'a> Foo<'static> for &'a i32 {
+   |          ^^^^^^^^^^^^
+   = note: expected  `Foo<'static>`
+              found  `Foo<'static>`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that the type `&i32` will meet its required lifetime bounds
   --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
@@ -30,9 +34,13 @@
    |
 LL | impl<'a,'b> Foo<'b> for &'a i64 {
    |      ^^
-   = note: ...so that the types are compatible:
-           expected Foo<'b>
-              found Foo<'_>
+note: ...so that the types are compatible
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
+   |
+LL | impl<'a,'b> Foo<'b> for &'a i64 {
+   |             ^^^^^^^
+   = note: expected  `Foo<'b>`
+              found  `Foo<'_>`
 note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9...
   --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9
    |
diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
index 81256e3..6a34871 100644
--- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
+++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
@@ -9,9 +9,13 @@
    |
 LL | impl<'a> Foo for &'a i32 {
    |      ^^
-   = note: ...so that the types are compatible:
-           expected Foo
-              found Foo
+note: ...so that the types are compatible
+  --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
+   |
+LL | impl<'a> Foo for &'a i32 {
+   |          ^^^
+   = note: expected  `Foo`
+              found  `Foo`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that the type `&i32` will meet its required lifetime bounds
   --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
index 8e473da..28873ab 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -15,9 +15,13 @@
 LL |     box B(&*v) as Box<dyn X>
    |           ^^^
    = note: but, the lifetime must be valid for the static lifetime...
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn X + 'static)>
-              found std::boxed::Box<dyn X>
+note: ...so that the expression is assignable
+  --> $DIR/regions-close-object-into-object-2.rs:10:5
+   |
+LL |     box B(&*v) as Box<dyn X>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected  `std::boxed::Box<(dyn X + 'static)>`
+              found  `std::boxed::Box<dyn X>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
index c80d13e..449a5b5 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -15,9 +15,13 @@
 LL |     box B(&*v) as Box<dyn X>
    |           ^^^
    = note: but, the lifetime must be valid for the static lifetime...
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn X + 'static)>
-              found std::boxed::Box<dyn X>
+note: ...so that the expression is assignable
+  --> $DIR/regions-close-object-into-object-4.rs:10:5
+   |
+LL |     box B(&*v) as Box<dyn X>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected  `std::boxed::Box<(dyn X + 'static)>`
+              found  `std::boxed::Box<dyn X>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
index ef21316..b2a7afa 100644
--- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
+++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
@@ -19,9 +19,13 @@
    |
 LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
    |                          ^^
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn SomeTrait + 'c)>
-              found std::boxed::Box<dyn SomeTrait>
+note: ...so that the expression is assignable
+  --> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
+   |
+LL |     box v as Box<dyn SomeTrait + 'a>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected  `std::boxed::Box<(dyn SomeTrait + 'c)>`
+              found  `std::boxed::Box<dyn SomeTrait>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-creating-enums4.stderr b/src/test/ui/regions/regions-creating-enums4.stderr
index 12b8978..58f74e4 100644
--- a/src/test/ui/regions/regions-creating-enums4.stderr
+++ b/src/test/ui/regions/regions-creating-enums4.stderr
@@ -9,17 +9,25 @@
    |
 LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
    |                ^^
-   = note: ...so that the expression is assignable:
-           expected &Ast<'_>
-              found &Ast<'a>
+note: ...so that the expression is assignable
+  --> $DIR/regions-creating-enums4.rs:7:14
+   |
+LL |     Ast::Add(x, y)
+   |              ^
+   = note: expected  `&Ast<'_>`
+              found  `&Ast<'a>`
 note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 6:19...
   --> $DIR/regions-creating-enums4.rs:6:19
    |
 LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
    |                   ^^
-   = note: ...so that the expression is assignable:
-           expected Ast<'b>
-              found Ast<'_>
+note: ...so that the expression is assignable
+  --> $DIR/regions-creating-enums4.rs:7:5
+   |
+LL |     Ast::Add(x, y)
+   |     ^^^^^^^^^^^^^^
+   = note: expected  `Ast<'b>`
+              found  `Ast<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-escape-method.stderr b/src/test/ui/regions/regions-escape-method.stderr
index b93dd0d..ffc2a259 100644
--- a/src/test/ui/regions/regions-escape-method.stderr
+++ b/src/test/ui/regions/regions-escape-method.stderr
@@ -9,9 +9,13 @@
    |
 LL |     s.f(|p| p)
    |         ^^^^^
-   = note: ...so that the expression is assignable:
-           expected &i32
-              found &i32
+note: ...so that the expression is assignable
+  --> $DIR/regions-escape-method.rs:15:13
+   |
+LL |     s.f(|p| p)
+   |             ^
+   = note: expected  `&i32`
+              found  `&i32`
 note: but, the lifetime must be valid for the method call at 15:5...
   --> $DIR/regions-escape-method.rs:15:5
    |
diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
index a6b165e..9082346 100644
--- a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
+++ b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr
@@ -9,9 +9,13 @@
    |
 LL |     with(|o| o)
    |          ^^^^^
-   = note: ...so that the expression is assignable:
-           expected &isize
-              found &isize
+note: ...so that the expression is assignable
+  --> $DIR/regions-escape-via-trait-or-not.rs:18:14
+   |
+LL |     with(|o| o)
+   |              ^
+   = note: expected  `&isize`
+              found  `&isize`
 note: but, the lifetime must be valid for the expression at 18:5...
   --> $DIR/regions-escape-via-trait-or-not.rs:18:5
    |
diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr
index f4eb5c8..8fce160 100644
--- a/src/test/ui/regions/regions-nested-fns.stderr
+++ b/src/test/ui/regions/regions-nested-fns.stderr
@@ -29,9 +29,18 @@
 LL | |         return z;
 LL | |     }));
    | |_____^
-   = note: ...so that the types are compatible:
-           expected &isize
-              found &isize
+note: ...so that the types are compatible
+  --> $DIR/regions-nested-fns.rs:13:76
+   |
+LL |       ignore::< Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+   |  ____________________________________________________________________________^
+LL | |         if false { return x; }
+LL | |         if false { return ay; }
+LL | |         return z;
+LL | |     }));
+   | |_____^
+   = note: expected  `&isize`
+              found  `&isize`
 
 error[E0312]: lifetime of reference outlives lifetime of borrowed content...
   --> $DIR/regions-nested-fns.rs:14:27
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
index d29fd80..8a600d2 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -17,9 +17,16 @@
    |
 LL | fn bar<'a, 'b>()
    |            ^^
-   = note: ...so that the types are compatible:
-           expected Project<'a, 'b>
-              found Project<'_, '_>
+note: ...so that the types are compatible
+  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+   |
+LL | / fn bar<'a, 'b>()
+LL | |     where <() as Project<'a, 'b>>::Item : Eq
+LL | | {
+LL | | }
+   | |_^
+   = note: expected  `Project<'a, 'b>`
+              found  `Project<'_, '_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr
index 4907667..2895a0c 100644
--- a/src/test/ui/regions/regions-ret-borrowed-1.stderr
+++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr
@@ -9,9 +9,13 @@
    |
 LL |     with(|o| o)
    |          ^^^^^
-   = note: ...so that the expression is assignable:
-           expected &isize
-              found &isize
+note: ...so that the expression is assignable
+  --> $DIR/regions-ret-borrowed-1.rs:10:14
+   |
+LL |     with(|o| o)
+   |              ^
+   = note: expected  `&isize`
+              found  `&isize`
 note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 9:14...
   --> $DIR/regions-ret-borrowed-1.rs:9:14
    |
diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr
index eb1ade2..b74f10f 100644
--- a/src/test/ui/regions/regions-ret-borrowed.stderr
+++ b/src/test/ui/regions/regions-ret-borrowed.stderr
@@ -9,9 +9,13 @@
    |
 LL |     with(|o| o)
    |          ^^^^^
-   = note: ...so that the expression is assignable:
-           expected &isize
-              found &isize
+note: ...so that the expression is assignable
+  --> $DIR/regions-ret-borrowed.rs:13:14
+   |
+LL |     with(|o| o)
+   |              ^
+   = note: expected  `&isize`
+              found  `&isize`
 note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 12:14...
   --> $DIR/regions-ret-borrowed.rs:12:14
    |
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr
index ef69f25..58b79d2 100644
--- a/src/test/ui/regions/regions-trait-object-subtyping.stderr
+++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr
@@ -36,9 +36,13 @@
    |
 LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
    |            ^^
-   = note: ...so that the expression is assignable:
-           expected &'b mut (dyn Dummy + 'b)
-              found &mut (dyn Dummy + 'b)
+note: ...so that the expression is assignable
+  --> $DIR/regions-trait-object-subtyping.rs:15:5
+   |
+LL |     x
+   |     ^
+   = note: expected  `&'b mut (dyn Dummy + 'b)`
+              found  `&mut (dyn Dummy + 'b)`
 
 error[E0308]: mismatched types
   --> $DIR/regions-trait-object-subtyping.rs:22:5
diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr
index e55f023..527babb 100644
--- a/src/test/ui/reject-specialized-drops-8142.stderr
+++ b/src/test/ui/reject-specialized-drops-8142.stderr
@@ -105,9 +105,13 @@
    |
 LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
    |               ^^^
-   = note: ...so that the types are compatible:
-           expected W<'l1, 'l2>
-              found W<'_, '_>
+note: ...so that the types are compatible
+  --> $DIR/reject-specialized-drops-8142.rs:54:1
+   |
+LL | impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected  `W<'l1, 'l2>`
+              found  `W<'_, '_>`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/resolve/impl-items-vis-unresolved.rs b/src/test/ui/resolve/impl-items-vis-unresolved.rs
new file mode 100644
index 0000000..9b4fe49
--- /dev/null
+++ b/src/test/ui/resolve/impl-items-vis-unresolved.rs
@@ -0,0 +1,25 @@
+// Visibilities on impl items expanded from macros are resolved (issue #64705).
+
+macro_rules! perftools_inline {
+    ($($item:tt)*) => (
+        $($item)*
+    );
+}
+
+mod state {
+    pub struct RawFloatState;
+    impl RawFloatState {
+        perftools_inline! {
+            pub(super) fn new() {} // OK
+        }
+    }
+}
+
+pub struct RawFloatState;
+impl RawFloatState {
+    perftools_inline! {
+        pub(super) fn new() {} //~ ERROR failed to resolve: there are too many initial `super`s
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/impl-items-vis-unresolved.stderr b/src/test/ui/resolve/impl-items-vis-unresolved.stderr
new file mode 100644
index 0000000..8e285e5
--- /dev/null
+++ b/src/test/ui/resolve/impl-items-vis-unresolved.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: there are too many initial `super`s.
+  --> $DIR/impl-items-vis-unresolved.rs:21:13
+   |
+LL |         pub(super) fn new() {}
+   |             ^^^^^ there are too many initial `super`s.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
index bbc25d4..8516baf 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
@@ -6,3 +6,6 @@
     Tuple(u32),
     Struct { field: u32 }
 }
+
+#[non_exhaustive]
+pub enum EmptyNonExhaustiveEnum {}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.rs b/src/test/ui/rfc-2008-non-exhaustive/enum.rs
index 7423a97..802f20b 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/enum.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum.rs
@@ -1,7 +1,14 @@
 // aux-build:enums.rs
 extern crate enums;
 
-use enums::NonExhaustiveEnum;
+use enums::{EmptyNonExhaustiveEnum, NonExhaustiveEnum};
+
+fn empty(x: EmptyNonExhaustiveEnum) {
+    match x {} //~ ERROR type `enums::EmptyNonExhaustiveEnum` is non-empty
+    match x {
+        _ => {}, // ok
+    }
+}
 
 fn main() {
     let enum_unit = NonExhaustiveEnum::Unit;
@@ -13,6 +20,9 @@
         NonExhaustiveEnum::Struct { .. } => "third"
     };
 
+    match enum_unit {};
+    //~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
+
     // Everything below this is expected to compile successfully.
 
     let enum_unit = NonExhaustiveEnum::Unit;
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
index b5c1a4e..a2bdcba 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr
@@ -1,11 +1,27 @@
+error[E0004]: non-exhaustive patterns: type `enums::EmptyNonExhaustiveEnum` is non-empty
+  --> $DIR/enum.rs:7:11
+   |
+LL |     match x {}
+   |           ^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/enum.rs:9:11
+  --> $DIR/enum.rs:16:11
    |
 LL |     match enum_unit {
    |           ^^^^^^^^^ pattern `_` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error: aborting due to previous error
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/enum.rs:23:11
+   |
+LL |     match enum_unit {};
+   |           ^^^^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs
new file mode 100644
index 0000000..afd6d99
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs
@@ -0,0 +1,37 @@
+#![deny(unreachable_patterns)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+    Unit,
+    //~^ not covered
+    Tuple(u32),
+    //~^ not covered
+    Struct { field: u32 }
+    //~^ not covered
+}
+
+pub enum NormalEnum {
+    Unit,
+    //~^ not covered
+    Tuple(u32),
+    //~^ not covered
+    Struct { field: u32 }
+    //~^ not covered
+}
+
+#[non_exhaustive]
+pub enum EmptyNonExhaustiveEnum {}
+
+fn empty_non_exhaustive(x: EmptyNonExhaustiveEnum) {
+    match x {}
+    match x {
+        _ => {} // not detected as unreachable
+    }
+}
+
+fn main() {
+    match NonExhaustiveEnum::Unit {}
+    //~^ ERROR `Unit`, `Tuple(_)` and `Struct { .. }` not covered [E0004]
+    match NormalEnum::Unit {}
+    //~^ ERROR `Unit`, `Tuple(_)` and `Struct { .. }` not covered [E0004]
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
new file mode 100644
index 0000000..a99a690
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
@@ -0,0 +1,45 @@
+error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+  --> $DIR/enum_same_crate_empty_match.rs:33:11
+   |
+LL | / pub enum NonExhaustiveEnum {
+LL | |     Unit,
+   | |     ---- not covered
+LL | |
+LL | |     Tuple(u32),
+   | |     ----- not covered
+LL | |
+LL | |     Struct { field: u32 }
+   | |     ------ not covered
+LL | |
+LL | | }
+   | |_- `NonExhaustiveEnum` defined here
+...
+LL |       match NonExhaustiveEnum::Unit {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+  --> $DIR/enum_same_crate_empty_match.rs:35:11
+   |
+LL | / pub enum NormalEnum {
+LL | |     Unit,
+   | |     ---- not covered
+LL | |
+LL | |     Tuple(u32),
+   | |     ----- not covered
+LL | |
+LL | |     Struct { field: u32 }
+   | |     ------ not covered
+LL | |
+LL | | }
+   | |_- `NormalEnum` defined here
+...
+LL |       match NormalEnum::Unit {}
+   |             ^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
index b903e9b..0d669a9a 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
@@ -1,4 +1,4 @@
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `uninhabited::IndirectUninhabitedEnum` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedEnum` is non-empty
   --> $DIR/indirect_match.rs:18:11
    |
 LL |     match x {}
@@ -6,7 +6,7 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `uninhabited::IndirectUninhabitedStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedStruct` is non-empty
   --> $DIR/indirect_match.rs:22:11
    |
 LL |     match x {}
@@ -14,7 +14,7 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `uninhabited::IndirectUninhabitedTupleStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedTupleStruct` is non-empty
   --> $DIR/indirect_match.rs:26:11
    |
 LL |     match x {}
@@ -22,7 +22,7 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `uninhabited::IndirectUninhabitedVariants` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedVariants` is non-empty
   --> $DIR/indirect_match.rs:32:11
    |
 LL |     match x {}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
index f94616d..41a37cf 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
@@ -1,53 +1,41 @@
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `IndirectUninhabitedEnum` is not handled
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
   --> $DIR/indirect_match_same_crate.rs:32:11
    |
 LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
-   | ----------------------------------------------------
-   | |          |
-   | |          variant not covered
-   | `IndirectUninhabitedEnum` defined here
+   | ---------------------------------------------------- `IndirectUninhabitedEnum` defined here
 ...
 LL |     match x {}
    |           ^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `IndirectUninhabitedStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
   --> $DIR/indirect_match_same_crate.rs:36:11
    |
 LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
-   | --------------------------------------------------------
-   | |          |
-   | |          variant not covered
-   | `IndirectUninhabitedStruct` defined here
+   | -------------------------------------------------------- `IndirectUninhabitedStruct` defined here
 ...
 LL |     match x {}
    |           ^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `IndirectUninhabitedTupleStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
   --> $DIR/indirect_match_same_crate.rs:40:11
    |
 LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
-   | ------------------------------------------------------------------
-   | |          |
-   | |          variant not covered
-   | `IndirectUninhabitedTupleStruct` defined here
+   | ------------------------------------------------------------------ `IndirectUninhabitedTupleStruct` defined here
 ...
 LL |     match x {}
    |           ^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `IndirectUninhabitedVariants` is not handled
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
   --> $DIR/indirect_match_same_crate.rs:46:11
    |
 LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
-   | ------------------------------------------------------------
-   | |          |
-   | |          variant not covered
-   | `IndirectUninhabitedVariants` defined here
+   | ------------------------------------------------------------ `IndirectUninhabitedVariants` defined here
 ...
 LL |     match x {}
    |           ^
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr
index de3fa90..10a456a 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr
@@ -6,7 +6,7 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `uninhabited::UninhabitedStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedStruct` is non-empty
   --> $DIR/match.rs:22:11
    |
 LL |     match x {}
@@ -14,7 +14,7 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `uninhabited::UninhabitedTupleStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedTupleStruct` is non-empty
   --> $DIR/match.rs:26:11
    |
 LL |     match x {}
@@ -22,11 +22,11 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: multiple patterns of type `uninhabited::UninhabitedVariants` are not handled
+error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered
   --> $DIR/match.rs:30:11
    |
 LL |     match x {}
-   |           ^
+   |           ^ patterns `Tuple(_)` and `Struct { .. }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
index 3dd1a91..148af8c 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
@@ -1,10 +1,7 @@
-error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `UninhabitedStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
   --> $DIR/match_same_crate.rs:28:11
    |
-LL |   pub struct UninhabitedStruct {
-   |   -          ----------------- variant not covered
-   |  _|
-   | |
+LL | / pub struct UninhabitedStruct {
 LL | |     _priv: !,
 LL | | }
    | |_- `UninhabitedStruct` defined here
@@ -14,33 +11,30 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `UninhabitedTupleStruct` is not handled
+error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
   --> $DIR/match_same_crate.rs:32:11
    |
 LL | pub struct UninhabitedTupleStruct(!);
-   | -------------------------------------
-   | |          |
-   | |          variant not covered
-   | `UninhabitedTupleStruct` defined here
+   | ------------------------------------- `UninhabitedTupleStruct` defined here
 ...
 LL |     match x {}
    |           ^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: multiple patterns of type `UninhabitedVariants` are not handled
+error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered
   --> $DIR/match_same_crate.rs:36:11
    |
 LL | / pub enum UninhabitedVariants {
 LL | |     #[non_exhaustive] Tuple(!),
-   | |                       ----- variant not covered
+   | |                       ----- not covered
 LL | |     #[non_exhaustive] Struct { x: ! }
-   | |                       ------ variant not covered
+   | |                       ------ not covered
 LL | | }
    | |_- `UninhabitedVariants` defined here
 ...
 LL |       match x {}
-   |             ^
+   |             ^ patterns `Tuple(_)` and `Struct { .. }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
index 3b56c68..2fc09c8 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
@@ -22,11 +22,11 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedVariants` is non-empty
+error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered
   --> $DIR/match_with_exhaustive_patterns.rs:33:11
    |
 LL |     match x {}
-   |           ^
+   |           ^ patterns `Tuple(_)` and `Struct { .. }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs
index 1c4d466..0a79aea 100644
--- a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs
+++ b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs
@@ -1,21 +1,27 @@
 // run-pass
 
-#![feature(core_intrinsics)]
+#![feature(track_caller)]
+
+#[inline(never)]
+#[track_caller]
+fn defeat_const_prop() -> &'static core::panic::Location<'static> {
+    core::panic::Location::caller()
+}
 
 macro_rules! caller_location_from_macro {
-    () => (core::intrinsics::caller_location());
+    () => (defeat_const_prop());
 }
 
 fn main() {
-    let loc = core::intrinsics::caller_location();
+    let loc = defeat_const_prop();
     assert_eq!(loc.file(), file!());
-    assert_eq!(loc.line(), 10);
+    assert_eq!(loc.line(), 16);
     assert_eq!(loc.column(), 15);
 
-    // `caller_location()` in a macro should behave similarly to `file!` and `line!`,
+    // `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
     // i.e. point to where the macro was invoked, instead of the macro itself.
     let loc2 = caller_location_from_macro!();
     assert_eq!(loc2.file(), file!());
-    assert_eq!(loc2.line(), 17);
+    assert_eq!(loc2.line(), 23);
     assert_eq!(loc2.column(), 16);
 }
diff --git a/src/test/ui/rfc-2091-track-caller/const-caller-location.rs b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs
new file mode 100644
index 0000000..0614c52
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs
@@ -0,0 +1,41 @@
+// run-pass
+
+#![feature(const_fn, track_caller)]
+
+use std::panic::Location;
+
+const LOCATION: &Location = Location::caller();
+
+const TRACKED: &Location = tracked();
+#[track_caller]
+const fn tracked() -> &'static Location <'static> {
+    Location::caller()
+}
+
+const NESTED: &Location = nested_location();
+const fn nested_location() -> &'static Location<'static> {
+    Location::caller()
+}
+
+const CONTAINED: &Location = contained();
+const fn contained() -> &'static Location<'static> {
+    tracked()
+}
+
+fn main() {
+    assert_eq!(LOCATION.file(), file!());
+    assert_eq!(LOCATION.line(), 7);
+    assert_eq!(LOCATION.column(), 29);
+
+    assert_eq!(TRACKED.file(), file!());
+    assert_eq!(TRACKED.line(), 9);
+    assert_eq!(TRACKED.column(), 28);
+
+    assert_eq!(NESTED.file(), file!());
+    assert_eq!(NESTED.line(), 17);
+    assert_eq!(NESTED.column(), 5);
+
+    assert_eq!(CONTAINED.file(), file!());
+    assert_eq!(CONTAINED.line(), 22);
+    assert_eq!(CONTAINED.column(), 5);
+}
diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
index d400db8..d656023 100644
--- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
@@ -1,4 +1,4 @@
-#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
+#![feature(track_caller)]
 
 #[track_caller(1)]
 fn f() {}
diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
index a53a8ee..8906fa5 100644
--- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
@@ -4,13 +4,5 @@
 LL | #[track_caller(1)]
    | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]`
 
-warning: the feature `track_caller` is incomplete and may cause the compiler to crash
-  --> $DIR/error-odd-syntax.rs:1:12
-   |
-LL | #![feature(track_caller)]
-   |            ^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
index 162c638..20d2961 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
@@ -1,6 +1,7 @@
-#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
+#![feature(track_caller)]
 
-#[track_caller] //~ ERROR Rust ABI is required to use `#[track_caller]`
+#[track_caller]
 extern "C" fn f() {}
+//~^^ ERROR `#[track_caller]` requires Rust ABI
 
 fn main() {}
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
index ad89b14..2a3a438 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
@@ -1,12 +1,4 @@
-warning: the feature `track_caller` is incomplete and may cause the compiler to crash
-  --> $DIR/error-with-invalid-abi.rs:1:12
-   |
-LL | #![feature(track_caller)]
-   |            ^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
-error[E0737]: Rust ABI is required to use `#[track_caller]`
+error[E0737]: `#[track_caller]` requires Rust ABI
   --> $DIR/error-with-invalid-abi.rs:3:1
    |
 LL | #[track_caller]
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
index bbbcec3..dd9e5d0 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
@@ -1,4 +1,4 @@
-#![feature(naked_functions, track_caller)] //~ WARN the feature `track_caller` is incomplete
+#![feature(naked_functions, track_caller)]
 
 #[track_caller]
 #[naked]
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
index 93e6f7a..2f5003c 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
@@ -1,11 +1,3 @@
-warning: the feature `track_caller` is incomplete and may cause the compiler to crash
-  --> $DIR/error-with-naked.rs:1:29
-   |
-LL | #![feature(naked_functions, track_caller)]
-   |                             ^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0736]: cannot use `#[track_caller]` with `#[naked]`
   --> $DIR/error-with-naked.rs:3:1
    |
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs
index 4fd768d..ef037ab 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs
@@ -1,4 +1,4 @@
-#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
+#![feature(track_caller)]
 
 trait Trait {
     #[track_caller] //~ ERROR: `#[track_caller]` may not be used on trait methods
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr
index 72ed6f8..ded721d 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr
@@ -1,11 +1,3 @@
-warning: the feature `track_caller` is incomplete and may cause the compiler to crash
-  --> $DIR/error-with-trait-decl.rs:1:12
-   |
-LL | #![feature(track_caller)]
-   |            ^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0738]: `#[track_caller]` may not be used on trait methods
   --> $DIR/error-with-trait-decl.rs:4:5
    |
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs
index 2139ba5..17e4bf4 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs
@@ -1,4 +1,4 @@
-#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
+#![feature(track_caller)]
 
 trait Trait {
     #[track_caller] //~ ERROR: `#[track_caller]` may not be used on trait methods
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr
index 05689c9..867eb91 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr
@@ -1,11 +1,3 @@
-warning: the feature `track_caller` is incomplete and may cause the compiler to crash
-  --> $DIR/error-with-trait-default-impl.rs:1:12
-   |
-LL | #![feature(track_caller)]
-   |            ^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0738]: `#[track_caller]` may not be used on trait methods
   --> $DIR/error-with-trait-default-impl.rs:4:5
    |
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs
index b565e11..75f20f7 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs
@@ -1,6 +1,6 @@
 // check-fail
 
-#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
+#![feature(track_caller)]
 
 trait Trait {
     fn unwrap(&self);
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr
index 707b367..fafceef 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr
@@ -1,11 +1,3 @@
-warning: the feature `track_caller` is incomplete and may cause the compiler to crash
-  --> $DIR/error-with-trait-fn-impl.rs:3:12
-   |
-LL | #![feature(track_caller)]
-   |            ^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0738]: `#[track_caller]` may not be used on trait methods
   --> $DIR/error-with-trait-fn-impl.rs:10:5
    |
diff --git a/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
new file mode 100644
index 0000000..76e62b8
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+#![feature(track_caller)]
+
+macro_rules! caller_location_from_macro {
+    () => (core::panic::Location::caller());
+}
+
+fn main() {
+    let loc = core::panic::Location::caller();
+    assert_eq!(loc.file(), file!());
+    assert_eq!(loc.line(), 10);
+    assert_eq!(loc.column(), 15);
+
+    // `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
+    // i.e. point to where the macro was invoked, instead of the macro itself.
+    let loc2 = caller_location_from_macro!();
+    assert_eq!(loc2.file(), file!());
+    assert_eq!(loc2.line(), 17);
+    assert_eq!(loc2.column(), 16);
+}
diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
index 01ebf13..0fd59b4 100644
--- a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
+++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
@@ -1,4 +1,4 @@
-#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
+#![feature(track_caller)]
 
 #[track_caller]
 struct S;
diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
index 3301da7..7becb9c 100644
--- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
+++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
@@ -1,11 +1,3 @@
-warning: the feature `track_caller` is incomplete and may cause the compiler to crash
-  --> $DIR/only-for-fns.rs:1:12
-   |
-LL | #![feature(track_caller)]
-   |            ^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0739]: attribute should be applied to function
   --> $DIR/only-for-fns.rs:3:1
    |
diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs
index f2c3f0d..eef83b3 100644
--- a/src/test/ui/rfc-2091-track-caller/pass.rs
+++ b/src/test/ui/rfc-2091-track-caller/pass.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
+#![feature(track_caller)]
 
 #[track_caller]
 fn f() {}
diff --git a/src/test/ui/rfc-2091-track-caller/pass.stderr b/src/test/ui/rfc-2091-track-caller/pass.stderr
deleted file mode 100644
index b1fd23a..0000000
--- a/src/test/ui/rfc-2091-track-caller/pass.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-warning: the feature `track_caller` is incomplete and may cause the compiler to crash
-  --> $DIR/pass.rs:2:12
-   |
-LL | #![feature(track_caller)]
-   |            ^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-
diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
new file mode 100644
index 0000000..8436ee5
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
@@ -0,0 +1,40 @@
+// run-pass
+
+#![feature(const_fn, track_caller)]
+
+use std::panic::Location;
+
+#[track_caller]
+fn tracked() -> &'static Location<'static> {
+    Location::caller()
+}
+
+fn nested_intrinsic() -> &'static Location<'static> {
+    Location::caller()
+}
+
+fn nested_tracked() -> &'static Location<'static> {
+    tracked()
+}
+
+fn main() {
+    let location = Location::caller();
+    assert_eq!(location.file(), file!());
+    assert_eq!(location.line(), 21);
+    assert_eq!(location.column(), 20);
+
+    let tracked = tracked();
+    assert_eq!(tracked.file(), file!());
+    assert_eq!(tracked.line(), 26);
+    assert_eq!(tracked.column(), 19);
+
+    let nested = nested_intrinsic();
+    assert_eq!(nested.file(), file!());
+    assert_eq!(nested.line(), 13);
+    assert_eq!(nested.column(), 5);
+
+    let contained = nested_tracked();
+    assert_eq!(contained.file(), file!());
+    assert_eq!(contained.line(), 17);
+    assert_eq!(contained.column(), 5);
+}
diff --git a/src/test/ui/self/self-vs-path-ambiguity.stderr b/src/test/ui/self/self-vs-path-ambiguity.stderr
index 5ce6a81..2beef50 100644
--- a/src/test/ui/self/self-vs-path-ambiguity.stderr
+++ b/src/test/ui/self/self-vs-path-ambiguity.stderr
@@ -2,7 +2,7 @@
   --> $DIR/self-vs-path-ambiguity.rs:9:11
    |
 LL |     fn i(&'a self::S: &S) {}
-   |           ^^ unexpected lifetime
+   |           ^^ help: remove the lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.rs b/src/test/ui/span/issue-42234-unknown-receiver-type.rs
index 58138e2..d3292bb 100644
--- a/src/test/ui/span/issue-42234-unknown-receiver-type.rs
+++ b/src/test/ui/span/issue-42234-unknown-receiver-type.rs
@@ -9,8 +9,8 @@
 }
 
 fn courier_to_des_moines_and_points_west(data: &[u32]) -> String {
-    data.iter() //~ ERROR type annotations needed
-        .sum::<_>()
+    data.iter()
+        .sum::<_>() //~ ERROR type annotations needed
         .to_string()
 }
 
diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr
index 30c9adb..9824d87 100644
--- a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr
+++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr
@@ -4,16 +4,15 @@
 LL |     let x: Option<_> = None;
    |         - consider giving `x` the explicit type `std::option::Option<_>`, where the type parameter `T` is specified
 LL |     x.unwrap().method_that_could_exist_on_some_type();
-   |       ^^^^^^ cannot infer type for `T`
+   |       ^^^^^^ cannot infer type for type parameter `T`
    |
    = note: type must be known at this point
 
 error[E0282]: type annotations needed
-  --> $DIR/issue-42234-unknown-receiver-type.rs:12:5
+  --> $DIR/issue-42234-unknown-receiver-type.rs:13:10
    |
-LL | /     data.iter()
-LL | |         .sum::<_>()
-   | |___________________^ cannot infer type
+LL |         .sum::<_>()
+   |          ^^^ cannot infer type
    |
    = note: type must be known at this point
 
diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs
index b077d59..713b9eb 100644
--- a/src/test/ui/span/macro-ty-params.rs
+++ b/src/test/ui/span/macro-ty-params.rs
@@ -10,5 +10,4 @@
     foo::<T>!(); //~ ERROR generic arguments in macro path
     foo::<>!(); //~ ERROR generic arguments in macro path
     m!(Default<>); //~ ERROR generic arguments in macro path
-    //~^ ERROR unexpected generic arguments in path
 }
diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr
index 39b3edc..21683b2 100644
--- a/src/test/ui/span/macro-ty-params.stderr
+++ b/src/test/ui/span/macro-ty-params.stderr
@@ -10,17 +10,11 @@
 LL |     foo::<>!();
    |          ^^
 
-error: unexpected generic arguments in path
-  --> $DIR/macro-ty-params.rs:12:8
-   |
-LL |     m!(Default<>);
-   |        ^^^^^^^^^
-
 error: generic arguments in macro path
   --> $DIR/macro-ty-params.rs:12:15
    |
 LL |     m!(Default<>);
    |               ^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/span/type-annotations-needed-expr.stderr b/src/test/ui/span/type-annotations-needed-expr.stderr
index e32a542..8366285 100644
--- a/src/test/ui/span/type-annotations-needed-expr.stderr
+++ b/src/test/ui/span/type-annotations-needed-expr.stderr
@@ -2,7 +2,10 @@
   --> $DIR/type-annotations-needed-expr.rs:2:39
    |
 LL |     let _ = (vec![1,2,3]).into_iter().sum() as f64;
-   |                                       ^^^ cannot infer type for `S`
+   |                                       ^^^
+   |                                       |
+   |                                       cannot infer type for type parameter `S`
+   |                                       help: consider specifying the type argument in the method call: `sum::<S>`
    |
    = note: type must be known at this point
 
diff --git a/src/test/ui/suggestions/option-content-move2.rs b/src/test/ui/suggestions/option-content-move2.rs
new file mode 100644
index 0000000..88e8a5b
--- /dev/null
+++ b/src/test/ui/suggestions/option-content-move2.rs
@@ -0,0 +1,16 @@
+struct NotCopyable;
+
+fn func<F: FnMut() -> H, H: FnMut()>(_: F) {}
+
+fn parse() {
+    let mut var = None;
+    func(|| {
+        // Shouldn't suggest `move ||.as_ref()` here
+        move || {
+        //~^ ERROR: cannot move out of `var`
+            var = Some(NotCopyable);
+        }
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/option-content-move2.stderr b/src/test/ui/suggestions/option-content-move2.stderr
new file mode 100644
index 0000000..71f7453
--- /dev/null
+++ b/src/test/ui/suggestions/option-content-move2.stderr
@@ -0,0 +1,18 @@
+error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
+  --> $DIR/option-content-move2.rs:9:9
+   |
+LL |     let mut var = None;
+   |         ------- captured outer variable
+...
+LL |         move || {
+   |         ^^^^^^^ move out of `var` occurs here
+LL |
+LL |             var = Some(NotCopyable);
+   |             ---
+   |             |
+   |             move occurs because `var` has type `std::option::Option<NotCopyable>`, which does not implement the `Copy` trait
+   |             move occurs due to use in closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/raw-name-use-suggestion.rs b/src/test/ui/suggestions/raw-name-use-suggestion.rs
index 6c01383..0a8073c 100644
--- a/src/test/ui/suggestions/raw-name-use-suggestion.rs
+++ b/src/test/ui/suggestions/raw-name-use-suggestion.rs
@@ -5,5 +5,5 @@
 
 fn main() {
     foo::let(); //~ ERROR expected identifier, found keyword `let`
-    r#break(); //~ ERROR cannot find function `break` in this scope
+    r#break(); //~ ERROR cannot find function `r#break` in this scope
 }
diff --git a/src/test/ui/suggestions/raw-name-use-suggestion.stderr b/src/test/ui/suggestions/raw-name-use-suggestion.stderr
index 58eb87c..62b7631 100644
--- a/src/test/ui/suggestions/raw-name-use-suggestion.stderr
+++ b/src/test/ui/suggestions/raw-name-use-suggestion.stderr
@@ -20,7 +20,7 @@
 LL |     foo::r#let();
    |          ^^^^^
 
-error[E0425]: cannot find function `break` in this scope
+error[E0425]: cannot find function `r#break` in this scope
   --> $DIR/raw-name-use-suggestion.rs:8:5
    |
 LL |     r#break();
diff --git a/src/test/ui/tail-typeck.stderr b/src/test/ui/tail-typeck.stderr
index eeeb258..69f8ffa 100644
--- a/src/test/ui/tail-typeck.stderr
+++ b/src/test/ui/tail-typeck.stderr
@@ -5,6 +5,11 @@
    |           -----          ^^^ expected `isize`, found `usize`
    |           |
    |           expected `isize` because of return type
+   |
+help: you can convert an `usize` to `isize` and panic if the converted value wouldn't fit
+   |
+LL | fn f() -> isize { return g().try_into().unwrap(); }
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
index 88c9c47..9fdcd4d 100644
--- a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
+++ b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
@@ -14,9 +14,13 @@
    |
 LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
    |         ^^
-   = note: ...so that the types are compatible:
-           expected T1<'a>
-              found T1<'_>
+note: ...so that the types are compatible
+  --> $DIR/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:13
+   |
+LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
+   |             ^^^^^^^^^^
+   = note: expected  `T1<'a>`
+              found  `T1<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-static-method-generic-inference.stderr b/src/test/ui/traits/trait-static-method-generic-inference.stderr
index 22931c5..f9718da 100644
--- a/src/test/ui/traits/trait-static-method-generic-inference.stderr
+++ b/src/test/ui/traits/trait-static-method-generic-inference.stderr
@@ -1,11 +1,13 @@
-error[E0283]: type annotations needed: cannot resolve `_: base::HasNew<base::Foo>`
+error[E0283]: type annotations needed
   --> $DIR/trait-static-method-generic-inference.rs:24:25
    |
 LL |         fn new() -> T;
    |         -------------- required by `base::HasNew::new`
 ...
 LL |     let _f: base::Foo = base::HasNew::new();
-   |                         ^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^^ cannot infer type
+   |
+   = note: cannot resolve `_: base::HasNew<base::Foo>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr
index d7d2704..7bcda23 100644
--- a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr
+++ b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr
@@ -2,7 +2,7 @@
   --> $DIR/traits-multidispatch-convert-ambig-dest.rs:26:5
    |
 LL |     test(22, std::default::Default::default());
-   |     ^^^^ cannot infer type for `U`
+   |     ^^^^ cannot infer type for type parameter `U`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs
index 9194468..1becb1e 100644
--- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs
+++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs
@@ -9,6 +9,7 @@
 
 type Foo<V> = impl Trait<V>;
 //~^ ERROR could not find defining uses
+//~| ERROR the trait bound `T: TraitWithAssoc` is not satisfied
 
 trait Trait<U> {}
 
diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
index bb22d58..1eb4cf2 100644
--- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
+++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
@@ -1,5 +1,14 @@
+error[E0277]: the trait bound `T: TraitWithAssoc` is not satisfied
+  --> $DIR/bound_reduction2.rs:10:1
+   |
+LL | type Foo<V> = impl Trait<V>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitWithAssoc` is not implemented for `T`
+...
+LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+   |                  -- help: consider further restricting this bound: `T: TraitWithAssoc +`
+
 error: defining opaque type use does not fully define opaque type: generic parameter `V` is specified as concrete type `<T as TraitWithAssoc>::Assoc`
-  --> $DIR/bound_reduction2.rs:17:1
+  --> $DIR/bound_reduction2.rs:18:1
    |
 LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
 LL | |     ()
@@ -12,5 +21,6 @@
 LL | type Foo<V> = impl Trait<V>;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-inference/or_else-multiple-type-params.rs b/src/test/ui/type-inference/or_else-multiple-type-params.rs
new file mode 100644
index 0000000..b15de2a
--- /dev/null
+++ b/src/test/ui/type-inference/or_else-multiple-type-params.rs
@@ -0,0 +1,10 @@
+use std::process::{Command, Stdio};
+
+fn main() {
+    let process = Command::new("wc")
+        .stdout(Stdio::piped())
+        .spawn()
+        .or_else(|err| { //~ ERROR type annotations needed
+            panic!("oh no: {:?}", err);
+        }).unwrap();
+}
diff --git a/src/test/ui/type-inference/or_else-multiple-type-params.stderr b/src/test/ui/type-inference/or_else-multiple-type-params.stderr
new file mode 100644
index 0000000..141cc25
--- /dev/null
+++ b/src/test/ui/type-inference/or_else-multiple-type-params.stderr
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/or_else-multiple-type-params.rs:7:10
+   |
+LL |         .or_else(|err| {
+   |          ^^^^^^^
+   |          |
+   |          cannot infer type for type parameter `F`
+   |          help: consider specifying the type arguments in the method call: `or_else::<F, O>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type-inference/sort_by_key.rs b/src/test/ui/type-inference/sort_by_key.rs
new file mode 100644
index 0000000..afc4d90
--- /dev/null
+++ b/src/test/ui/type-inference/sort_by_key.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let mut lst: [([i32; 10], bool); 10] = [([0; 10], false); 10];
+    lst.sort_by_key(|&(v, _)| v.iter().sum()); //~ ERROR type annotations needed
+    println!("{:?}", lst);
+}
diff --git a/src/test/ui/type-inference/sort_by_key.stderr b/src/test/ui/type-inference/sort_by_key.stderr
new file mode 100644
index 0000000..1d386bd
--- /dev/null
+++ b/src/test/ui/type-inference/sort_by_key.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/sort_by_key.rs:3:9
+   |
+LL |     lst.sort_by_key(|&(v, _)| v.iter().sum());
+   |         ^^^^^^^^^^^                    --- help: consider specifying the type argument in the method call: `sum::<S>`
+   |         |
+   |         cannot infer type for type parameter `K`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type-inference/unbounded-associated-type.rs b/src/test/ui/type-inference/unbounded-associated-type.rs
new file mode 100644
index 0000000..0167e94
--- /dev/null
+++ b/src/test/ui/type-inference/unbounded-associated-type.rs
@@ -0,0 +1,16 @@
+trait T {
+    type A;
+    fn foo(&self) -> Self::A {
+        panic!()
+    }
+}
+
+struct S<X>(std::marker::PhantomData<X>);
+
+impl<X> T for S<X> {
+   type A = X;
+}
+
+fn main() {
+    S(std::marker::PhantomData).foo(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/type-inference/unbounded-associated-type.stderr b/src/test/ui/type-inference/unbounded-associated-type.stderr
new file mode 100644
index 0000000..726dd4b
--- /dev/null
+++ b/src/test/ui/type-inference/unbounded-associated-type.stderr
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed
+  --> $DIR/unbounded-associated-type.rs:15:5
+   |
+LL |     type A;
+   |     ------- `<Self as T>::A` defined here
+...
+LL |     S(std::marker::PhantomData).foo();
+   |     ^--------------------------------
+   |     |
+   |     this method call resolves to `<Self as T>::A`
+   |     cannot infer type for type parameter `X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs
new file mode 100644
index 0000000..81d054b
--- /dev/null
+++ b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs
@@ -0,0 +1,9 @@
+#[allow(invalid_type_param_default)]
+
+fn foo<T, U = u64>() -> (T, U) {
+    panic!()
+}
+
+fn main() {
+    foo(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr
new file mode 100644
index 0000000..52039d0
--- /dev/null
+++ b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:8:5
+   |
+LL |     foo();
+   |     ^^^ cannot infer type for type parameter `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn.rs b/src/test/ui/type-inference/unbounded-type-param-in-fn.rs
new file mode 100644
index 0000000..1f336ed
--- /dev/null
+++ b/src/test/ui/type-inference/unbounded-type-param-in-fn.rs
@@ -0,0 +1,7 @@
+fn foo<T>() -> T {
+    panic!()
+}
+
+fn main() {
+    foo(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr b/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr
new file mode 100644
index 0000000..8d317df
--- /dev/null
+++ b/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/unbounded-type-param-in-fn.rs:6:5
+   |
+LL |     foo();
+   |     ^^^ cannot infer type for type parameter `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type/type-annotation-needed.rs b/src/test/ui/type/type-annotation-needed.rs
index 3b1521d..a420515 100644
--- a/src/test/ui/type/type-annotation-needed.rs
+++ b/src/test/ui/type/type-annotation-needed.rs
@@ -5,4 +5,6 @@
 fn main() {
     foo(42);
     //~^ ERROR type annotations needed
+    //~| NOTE cannot infer type
+    //~| NOTE cannot resolve
 }
diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr
index 460bbe9..9442544 100644
--- a/src/test/ui/type/type-annotation-needed.stderr
+++ b/src/test/ui/type/type-annotation-needed.stderr
@@ -1,4 +1,4 @@
-error[E0283]: type annotations needed: cannot resolve `_: std::convert::Into<std::string::String>`
+error[E0283]: type annotations needed
   --> $DIR/type-annotation-needed.rs:6:5
    |
 LL | fn foo<T: Into<String>>(x: i32) {}
@@ -6,6 +6,11 @@
 ...
 LL |     foo(42);
    |     ^^^
+   |     |
+   |     cannot infer type for type parameter `T`
+   |     help: consider specifying the type argument in the function call: `foo::<T>`
+   |
+   = note: cannot resolve `_: std::convert::Into<std::string::String>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type/type-check-defaults.rs b/src/test/ui/type/type-check-defaults.rs
index 5748c9b..5380fae 100644
--- a/src/test/ui/type/type-check-defaults.rs
+++ b/src/test/ui/type/type-check-defaults.rs
@@ -4,9 +4,9 @@
 
 struct Foo<T, U: FromIterator<T>>(T, U);
 struct WellFormed<Z = Foo<i32, i32>>(Z);
-//~^ ERROR a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+//~^ ERROR a value of type `i32` cannot be built from an iterator over elements of type `i32`
 struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
-//~^ ERROR a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+//~^ ERROR a value of type `i32` cannot be built from an iterator over elements of type `i32`
 
 struct Bounds<T:Copy=String>(T);
 //~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr
index 6802bc3..6f84b37 100644
--- a/src/test/ui/type/type-check-defaults.stderr
+++ b/src/test/ui/type/type-check-defaults.stderr
@@ -1,21 +1,21 @@
-error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+error[E0277]: a value of type `i32` cannot be built from an iterator over elements of type `i32`
   --> $DIR/type-check-defaults.rs:6:19
    |
 LL | struct Foo<T, U: FromIterator<T>>(T, U);
    | ---------------------------------------- required by `Foo`
 LL | struct WellFormed<Z = Foo<i32, i32>>(Z);
-   |                   ^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
+   |                   ^ value of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
    |
    = help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
 
-error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+error[E0277]: a value of type `i32` cannot be built from an iterator over elements of type `i32`
   --> $DIR/type-check-defaults.rs:8:27
    |
 LL | struct Foo<T, U: FromIterator<T>>(T, U);
    | ---------------------------------------- required by `Foo`
 ...
 LL | struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
-   |                           ^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
+   |                           ^ value of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
    |
    = help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
 
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr
index 6524bf5..53cc769 100644
--- a/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr
@@ -2,7 +2,7 @@
   --> $DIR/cannot_infer_local_or_vec.rs:2:13
    |
 LL |     let x = vec![];
-   |         -   ^^^^^^ cannot infer type for `T`
+   |         -   ^^^^^^ cannot infer type for type parameter `T`
    |         |
    |         consider giving `x` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified
    |
diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
index 6d1ef240..df7228c 100644
--- a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
+++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
@@ -2,7 +2,7 @@
   --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18
    |
 LL |     let (x, ) = (vec![], );
-   |         -----    ^^^^^^ cannot infer type for `T`
+   |         -----    ^^^^^^ cannot infer type for type parameter `T`
    |         |
    |         consider giving this pattern the explicit type `(std::vec::Vec<T>,)`, where the type parameter `T` is specified
    |
diff --git a/src/test/ui/type/type-check/issue-22897.stderr b/src/test/ui/type/type-check/issue-22897.stderr
index 2b3f069..fae7b79 100644
--- a/src/test/ui/type/type-check/issue-22897.stderr
+++ b/src/test/ui/type/type-check/issue-22897.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-22897.rs:4:5
    |
 LL |     [];
-   |     ^^ cannot infer type for `[_; 0]`
+   |     ^^ cannot infer type for array `[_; 0]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr
index 508783a..4fc0285 100644
--- a/src/test/ui/type/type-check/issue-40294.stderr
+++ b/src/test/ui/type/type-check/issue-40294.stderr
@@ -1,4 +1,4 @@
-error[E0283]: type annotations needed: cannot resolve `&'a T: Foo`
+error[E0283]: type annotations needed
   --> $DIR/issue-40294.rs:5:1
    |
 LL |   trait Foo: Sized {
@@ -11,7 +11,9 @@
 LL | |     x.foo();
 LL | |     y.foo();
 LL | | }
-   | |_^
+   | |_^ cannot infer type for reference `&'a T`
+   |
+   = note: cannot resolve `&'a T: Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs
new file mode 100644
index 0000000..e23c0d0
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs
@@ -0,0 +1,27 @@
+fn main() {
+    let mut i: i64;
+    // Expected type is an inference variable `?T`
+    // because the `match` is used as a statement.
+    // This is the "initial" type of the `coercion`.
+    match i {
+        // Add `bool` to the overall `coercion`.
+        0 => true,
+
+        // Necessary to cause the ICE:
+        1 => true,
+
+        // Suppose that we had `let _: bool = match i { ... }`.
+        // In that case, as the expected type would be `bool`,
+        // we would suggest `i == 1` as a fix.
+        //
+        // However, no type error happens when checking `i = 1` because `expected == ?T`,
+        // which will unify with `typeof(i = 1) == ()`.
+        //
+        // However, in #67273, we would delay the unification of this arm with the above
+        // because we used the hitherto accumulated coercion as opposed to the "initial" type.
+        2 => i = 1,
+        //~^ ERROR match arms have incompatible types
+
+        _ => (),
+    }
+}
diff --git a/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr
new file mode 100644
index 0000000..3547285
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr
@@ -0,0 +1,22 @@
+error[E0308]: match arms have incompatible types
+  --> $DIR/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs:22:14
+   |
+LL | /     match i {
+LL | |         // Add `bool` to the overall `coercion`.
+LL | |         0 => true,
+   | |              ---- this is found to be of type `bool`
+LL | |
+LL | |         // Necessary to cause the ICE:
+LL | |         1 => true,
+   | |              ---- this is found to be of type `bool`
+...  |
+LL | |         2 => i = 1,
+   | |              ^^^^^ expected `bool`, found `()`
+...  |
+LL | |         _ => (),
+LL | |     }
+   | |_____- `match` arms have incompatible types
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.rs b/src/test/ui/type/type-dependent-def-issue-49241.rs
index 5ad50ff..a25e3ba 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.rs
+++ b/src/test/ui/type/type-dependent-def-issue-49241.rs
@@ -3,5 +3,5 @@
     const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
     let s: [u32; l] = v.into_iter().collect();
     //~^ ERROR evaluation of constant value failed
-    //~^^ ERROR a collection of type
+    //~^^ ERROR a value of type
 }
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr
index 851004d..18a69c5 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.stderr
+++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr
@@ -10,11 +10,11 @@
 LL |     let s: [u32; l] = v.into_iter().collect();
    |                  ^ referenced constant has errors
 
-error[E0277]: a collection of type `[u32; _]` cannot be built from an iterator over elements of type `{integer}`
+error[E0277]: a value of type `[u32; _]` cannot be built from an iterator over elements of type `{integer}`
   --> $DIR/type-dependent-def-issue-49241.rs:4:37
    |
 LL |     let s: [u32; l] = v.into_iter().collect();
-   |                                     ^^^^^^^ a collection of type `[u32; _]` cannot be built from `std::iter::Iterator<Item={integer}>`
+   |                                     ^^^^^^^ value of type `[u32; _]` cannot be built from `std::iter::Iterator<Item={integer}>`
    |
    = help: the trait `std::iter::FromIterator<{integer}>` is not implemented for `[u32; _]`
 
diff --git a/src/test/ui/unconstrained-none.stderr b/src/test/ui/unconstrained-none.stderr
index eb918b2..6c4fde9 100644
--- a/src/test/ui/unconstrained-none.stderr
+++ b/src/test/ui/unconstrained-none.stderr
@@ -2,7 +2,7 @@
   --> $DIR/unconstrained-none.rs:4:5
    |
 LL |     None;
-   |     ^^^^ cannot infer type for `T`
+   |     ^^^^ cannot infer type for type parameter `T`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unconstrained-ref.stderr b/src/test/ui/unconstrained-ref.stderr
index d9a129a..d6985a6 100644
--- a/src/test/ui/unconstrained-ref.stderr
+++ b/src/test/ui/unconstrained-ref.stderr
@@ -2,7 +2,7 @@
   --> $DIR/unconstrained-ref.rs:6:5
    |
 LL |     S { o: &None };
-   |     ^ cannot infer type for `T`
+   |     ^ cannot infer type for type parameter `T`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index d0475bf..e6029e0d 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -18,9 +18,13 @@
 LL |     Box::new(items.iter())
    |              ^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
-   = note: ...so that the expression is assignable:
-           expected std::boxed::Box<(dyn std::iter::Iterator<Item = &T> + 'static)>
-              found std::boxed::Box<dyn std::iter::Iterator<Item = &T>>
+note: ...so that the expression is assignable
+  --> $DIR/dyn-trait-underscore.rs:8:5
+   |
+LL |     Box::new(items.iter())
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected  `std::boxed::Box<(dyn std::iter::Iterator<Item = &T> + 'static)>`
+              found  `std::boxed::Box<dyn std::iter::Iterator<Item = &T>>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index 7af6075..18ffdcc 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -9,6 +9,9 @@
 error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:12:19
    |
+LL | enum Void {}
+   | ------------ `Void` defined here
+...
 LL |     let _ = match x {};
    |                   ^
    |
diff --git a/src/test/ui/vector-no-ann.stderr b/src/test/ui/vector-no-ann.stderr
index 28100d7..62fc42f 100644
--- a/src/test/ui/vector-no-ann.stderr
+++ b/src/test/ui/vector-no-ann.stderr
@@ -2,7 +2,7 @@
   --> $DIR/vector-no-ann.rs:2:16
    |
 LL |     let _foo = Vec::new();
-   |         ----   ^^^^^^^^ cannot infer type for `T`
+   |         ----   ^^^^^^^^ cannot infer type for type parameter `T`
    |         |
    |         consider giving `_foo` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified
 
diff --git a/src/test/ui/wrong-ret-type.stderr b/src/test/ui/wrong-ret-type.stderr
index 440620f..c1274bd 100644
--- a/src/test/ui/wrong-ret-type.stderr
+++ b/src/test/ui/wrong-ret-type.stderr
@@ -5,6 +5,11 @@
    |                -----                            ^ expected `usize`, found `isize`
    |                |
    |                expected `usize` because of return type
+   |
+help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+   |
+LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); }
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index dc4811e..46cce63 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -71,6 +71,7 @@
     pub ignore: Ignore,
     pub should_fail: bool,
     pub aux: Vec<String>,
+    pub aux_crate: Vec<(String, String)>,
     pub revisions: Vec<String>,
 }
 
@@ -80,6 +81,7 @@
             ignore: Ignore::Run,
             should_fail: false,
             aux: Vec::new(),
+            aux_crate: Vec::new(),
             revisions: vec![],
         };
 
@@ -157,6 +159,10 @@
                 props.aux.push(s);
             }
 
+            if let Some(ac) = config.parse_aux_crate(ln) {
+                props.aux_crate.push(ac);
+            }
+
             if let Some(r) = config.parse_revisions(ln) {
                 props.revisions.extend(r);
             }
@@ -311,10 +317,9 @@
     // directory as the test, but for backwards compatibility reasons
     // we also check the auxiliary directory)
     pub aux_builds: Vec<String>,
-    // A list of crates to pass '--extern-private name:PATH' flags for
-    // This should be a subset of 'aux_build'
-    // FIXME: Replace this with a better solution: https://github.com/rust-lang/rust/pull/54020
-    pub extern_private: Vec<String>,
+    // Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies
+    // to build and pass with the `--extern` flag.
+    pub aux_crates: Vec<(String, String)>,
     // Environment settings to use for compiling
     pub rustc_env: Vec<(String, String)>,
     // Environment variables to unset prior to compiling.
@@ -387,7 +392,7 @@
             run_flags: None,
             pp_exact: None,
             aux_builds: vec![],
-            extern_private: vec![],
+            aux_crates: vec![],
             revisions: vec![],
             rustc_env: vec![],
             unset_rustc_env: vec![],
@@ -514,8 +519,8 @@
                 self.aux_builds.push(ab);
             }
 
-            if let Some(ep) = config.parse_extern_private(ln) {
-                self.extern_private.push(ep);
+            if let Some(ac) = config.parse_aux_crate(ln) {
+                self.aux_crates.push(ac);
             }
 
             if let Some(ee) = config.parse_env(ln, "exec-env") {
@@ -713,8 +718,14 @@
             .map(|r| r.trim().to_string())
     }
 
-    fn parse_extern_private(&self, line: &str) -> Option<String> {
-        self.parse_name_value_directive(line, "extern-private")
+    fn parse_aux_crate(&self, line: &str) -> Option<(String, String)> {
+        self.parse_name_value_directive(line, "aux-crate").map(|r| {
+            let mut parts = r.trim().splitn(2, '=');
+            (
+                parts.next().expect("aux-crate name").to_string(),
+                parts.next().expect("aux-crate value").to_string(),
+            )
+        })
     }
 
     fn parse_compile_flags(&self, line: &str) -> Option<String> {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 15ae67f..4808684 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1776,93 +1776,16 @@
             create_dir_all(&aux_dir).unwrap();
         }
 
-        // Use a Vec instead of a HashMap to preserve original order
-        let mut extern_priv = self.props.extern_private.clone();
-
-        let mut add_extern_priv = |priv_dep: &str, dylib: bool| {
-            let lib_name = get_lib_name(priv_dep, dylib);
-            rustc
-                .arg("--extern-private")
-                .arg(format!("{}={}", priv_dep, aux_dir.join(lib_name).to_str().unwrap()));
-        };
-
         for rel_ab in &self.props.aux_builds {
-            let aux_testpaths = self.compute_aux_test_paths(rel_ab);
-            let aux_props =
-                self.props
-                    .from_aux_file(&aux_testpaths.file, self.revision, self.config);
-            let aux_output = TargetLocation::ThisDirectory(self.aux_output_dir_name());
-            let aux_cx = TestCx {
-                config: self.config,
-                props: &aux_props,
-                testpaths: &aux_testpaths,
-                revision: self.revision,
-            };
-            // Create the directory for the stdout/stderr files.
-            create_dir_all(aux_cx.output_base_dir()).unwrap();
-            let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output);
-
-            let (dylib, crate_type) = if aux_props.no_prefer_dynamic {
-                (true, None)
-            } else if self.config.target.contains("cloudabi")
-                || self.config.target.contains("emscripten")
-                || (self.config.target.contains("musl")
-                    && !aux_props.force_host
-                    && !self.config.host.contains("musl"))
-                || self.config.target.contains("wasm32")
-                || self.config.target.contains("nvptx")
-                || self.is_vxworks_pure_static()
-            {
-                // We primarily compile all auxiliary libraries as dynamic libraries
-                // to avoid code size bloat and large binaries as much as possible
-                // for the test suite (otherwise including libstd statically in all
-                // executables takes up quite a bit of space).
-                //
-                // For targets like MUSL or Emscripten, however, there is no support for
-                // dynamic libraries so we just go back to building a normal library. Note,
-                // however, that for MUSL if the library is built with `force_host` then
-                // it's ok to be a dylib as the host should always support dylibs.
-                (false, Some("lib"))
-            } else {
-                (true, Some("dylib"))
-            };
-
-            let trimmed = rel_ab.trim_end_matches(".rs").to_string();
-
-            // Normally, every 'extern-private' has a correspodning 'aux-build'
-            // entry. If so, we remove it from our list of private crates,
-            // and add an '--extern-private' flag to rustc
-            if extern_priv.remove_item(&trimmed).is_some() {
-                add_extern_priv(&trimmed, dylib);
-            }
-
-            if let Some(crate_type) = crate_type {
-                aux_rustc.args(&["--crate-type", crate_type]);
-            }
-
-            aux_rustc.arg("-L").arg(&aux_dir);
-
-            let auxres = aux_cx.compose_and_run(
-                aux_rustc,
-                aux_cx.config.compile_lib_path.to_str().unwrap(),
-                Some(aux_dir.to_str().unwrap()),
-                None,
-            );
-            if !auxres.status.success() {
-                self.fatal_proc_rec(
-                    &format!(
-                        "auxiliary build of {:?} failed to compile: ",
-                        aux_testpaths.file.display()
-                    ),
-                    &auxres,
-                );
-            }
+            self.build_auxiliary(rel_ab, &aux_dir);
         }
 
-        // Add any '--extern-private' entries without a matching
-        // 'aux-build'
-        for private_lib in extern_priv {
-            add_extern_priv(&private_lib, true);
+        for (aux_name, aux_path) in &self.props.aux_crates {
+            let is_dylib = self.build_auxiliary(&aux_path, &aux_dir);
+            let lib_name = get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"),
+                is_dylib);
+            rustc.arg("--extern")
+                .arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name));
         }
 
         self.props.unset_rustc_env.clone()
@@ -1877,6 +1800,74 @@
         )
     }
 
+    /// Builds an aux dependency.
+    ///
+    /// Returns whether or not it is a dylib.
+    fn build_auxiliary(&self, source_path: &str, aux_dir: &Path) -> bool {
+        let aux_testpaths = self.compute_aux_test_paths(source_path);
+        let aux_props =
+            self.props
+                .from_aux_file(&aux_testpaths.file, self.revision, self.config);
+        let aux_output = TargetLocation::ThisDirectory(self.aux_output_dir_name());
+        let aux_cx = TestCx {
+            config: self.config,
+            props: &aux_props,
+            testpaths: &aux_testpaths,
+            revision: self.revision,
+        };
+        // Create the directory for the stdout/stderr files.
+        create_dir_all(aux_cx.output_base_dir()).unwrap();
+        let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output);
+
+        let (dylib, crate_type) = if aux_props.no_prefer_dynamic {
+            (true, None)
+        } else if self.config.target.contains("cloudabi")
+            || self.config.target.contains("emscripten")
+            || (self.config.target.contains("musl")
+                && !aux_props.force_host
+                && !self.config.host.contains("musl"))
+            || self.config.target.contains("wasm32")
+            || self.config.target.contains("nvptx")
+            || self.is_vxworks_pure_static()
+        {
+            // We primarily compile all auxiliary libraries as dynamic libraries
+            // to avoid code size bloat and large binaries as much as possible
+            // for the test suite (otherwise including libstd statically in all
+            // executables takes up quite a bit of space).
+            //
+            // For targets like MUSL or Emscripten, however, there is no support for
+            // dynamic libraries so we just go back to building a normal library. Note,
+            // however, that for MUSL if the library is built with `force_host` then
+            // it's ok to be a dylib as the host should always support dylibs.
+            (false, Some("lib"))
+        } else {
+            (true, Some("dylib"))
+        };
+
+        if let Some(crate_type) = crate_type {
+            aux_rustc.args(&["--crate-type", crate_type]);
+        }
+
+        aux_rustc.arg("-L").arg(&aux_dir);
+
+        let auxres = aux_cx.compose_and_run(
+            aux_rustc,
+            aux_cx.config.compile_lib_path.to_str().unwrap(),
+            Some(aux_dir.to_str().unwrap()),
+            None,
+        );
+        if !auxres.status.success() {
+            self.fatal_proc_rec(
+                &format!(
+                    "auxiliary build of {:?} failed to compile: ",
+                    aux_testpaths.file.display()
+                ),
+                &auxres,
+            );
+        }
+        dylib
+    }
+
     fn compose_and_run(
         &self,
         mut command: Command,
diff --git a/src/tools/miri b/src/tools/miri
index a0ba079..048af40 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit a0ba079b6af0f8c07c33dd8af72a51c997e58967
+Subproject commit 048af409232fc2d7f8fbe5469080dc8bb702c498
diff --git a/src/tools/rls b/src/tools/rls
index 9ec2b8c..8f1c275 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 9ec2b8cb57c87517bcb506ac302eae339ffa2025
+Subproject commit 8f1c2756d76c3dd728b925b65eec0106eb3102ea
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
index 33e3667..1838235 160000
--- a/src/tools/rustfmt
+++ b/src/tools/rustfmt
@@ -1 +1 @@
-Subproject commit 33e3667085e4c73d4391c6168552458eb47664de
+Subproject commit 1838235248bbde125bbc6c12fb493e1979088bb5
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 7b928a2..36e4129 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -135,6 +135,7 @@
     Crate("polonius-engine"),
     Crate("ppv-lite86"),
     Crate("proc-macro2"),
+    Crate("punycode"),
     Crate("quick-error"),
     Crate("quote"),
     Crate("rand"),