Rollup merge of #63630 - andjo403:bump_compiler, r=nikomatsakis

Update installed compiler dependencies

As llvm have updated the minimum toolchain
https://reviews.llvm.org/D66188
diff --git a/.mailmap b/.mailmap
index 72c7600..9587aaa 100644
--- a/.mailmap
+++ b/.mailmap
@@ -184,12 +184,20 @@
 Nick Platt <platt.nicholas@gmail.com>
 Nicole Mazzuca <npmazzuca@gmail.com>
 Nif Ward <nif.ward@gmail.com>
-Oliver Schneider <oliver.schneider@kit.edu> oli-obk <github6541940@oli-obk.de>
-Oliver Schneider <oliver.schneider@kit.edu> Oliver 'ker' Schneider <rust19446194516@oli-obk.de>
-Oliver Schneider <oliver.schneider@kit.edu> Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
-Oliver Schneider <oliver.schneider@kit.edu> Oliver Schneider <git-spam9815368754983@oli-obk.de>
-Oliver Schneider <oliver.schneider@kit.edu> Oliver Schneider <github333195615777966@oli-obk.de>
-Oliver Schneider <oliver.schneider@kit.edu> Oliver Schneider <github6541940@oli-obk.de>
+Oliver Middleton <olliemail27@gmail.com> <ollie27@users.noreply.github.com>
+Oliver Scherer <oliver.schneider@kit.edu> <git-spam-no-reply9815368754983@oli-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu> <git-spam9815368754983@oli-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu> <github333195615777966@oli-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu> <github6541940@oli-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu> <rust19446194516@oli-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu> <git-no-reply-9879165716479413131@oli-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu> <git1984941651981@oli-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu> <github35764891676564198441@oli-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu> <github6541940@oli-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu> <oli-obk@users.noreply.github.com>
+Oliver Scherer <oliver.schneider@kit.edu> <public.oliver.schneider@kit.edu>
+Oliver Scherer <oliver.schneider@kit.edu> <obk8176014uqher834@olio-obk.de>
+Oliver Scherer <oliver.schneider@kit.edu>
 Ožbolt Menegatti <ozbolt.menegatti@gmail.com> gareins <ozbolt.menegatti@gmail.com>
 Paul Faria <paul_faria@ultimatesoftware.com> Paul Faria <Nashenas88@gmail.com>
 Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com> parir <peer.aramillo.irizar@gmail.com>
diff --git a/Cargo.lock b/Cargo.lock
index ae641d6..326f3b1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -109,9 +109,9 @@
 
 [[package]]
 name = "backtrace"
-version = "0.3.35"
+version = "0.3.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55"
+checksum = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2"
 dependencies = [
  "backtrace-sys",
  "cfg-if",
@@ -223,18 +223,18 @@
 
 [[package]]
 name = "bytecount"
-version = "0.5.1"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c"
+checksum = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e"
 dependencies = [
  "packed_simd",
 ]
 
 [[package]]
 name = "byteorder"
-version = "1.2.7"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
+checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
 
 [[package]]
 name = "bytes"
@@ -277,7 +277,7 @@
  "crypto-hash",
  "curl",
  "curl-sys",
- "env_logger 0.6.0",
+ "env_logger",
  "failure",
  "filetime",
  "flate2",
@@ -287,7 +287,7 @@
  "git2-curl",
  "glob",
  "hex",
- "home 0.5.0",
+ "home",
  "ignore",
  "im-rc",
  "jobserver",
@@ -309,7 +309,7 @@
  "same-file",
  "semver",
  "serde",
- "serde_ignored 0.1.0",
+ "serde_ignored",
  "serde_json",
  "shell-escape",
  "strip-ansi-escapes",
@@ -392,9 +392,9 @@
 
 [[package]]
 name = "clap"
-version = "2.32.0"
+version = "2.33.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
+checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
 dependencies = [
  "ansi_term",
  "atty",
@@ -507,7 +507,7 @@
 version = "0.0.0"
 dependencies = [
  "diff",
- "env_logger 0.5.13",
+ "env_logger",
  "getopts",
  "lazy_static 1.3.0",
  "libc",
@@ -753,9 +753,9 @@
 dependencies = [
  "fnv",
  "ident_case",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
 ]
 
 [[package]]
@@ -765,8 +765,8 @@
 checksum = "244e8987bd4e174385240cde20a3657f607fb0797563c28255c353b5819a07b1"
 dependencies = [
  "darling_core",
- "quote",
- "syn",
+ "quote 0.6.12",
+ "syn 0.15.35",
 ]
 
 [[package]]
@@ -781,9 +781,9 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
 ]
 
 [[package]]
@@ -792,10 +792,10 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871"
 dependencies = [
- "proc-macro2",
- "quote",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
  "rustc_version",
- "syn",
+ "syn 0.15.35",
 ]
 
 [[package]]
@@ -909,21 +909,9 @@
 
 [[package]]
 name = "env_logger"
-version = "0.5.13"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
-dependencies = [
- "atty",
- "humantime",
- "log",
- "termcolor",
-]
-
-[[package]]
-name = "env_logger"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
+checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
 dependencies = [
  "atty",
  "humantime",
@@ -965,9 +953,9 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
  "synstructure",
 ]
 
@@ -1011,6 +999,7 @@
 name = "fmt_macros"
 version = "0.0.0"
 dependencies = [
+ "rustc_lexer",
  "syntax_pos",
 ]
 
@@ -1150,12 +1139,13 @@
 
 [[package]]
 name = "getrandom"
-version = "0.1.8"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49"
+checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571"
 dependencies = [
  "cfg-if",
  "libc",
+ "wasi",
 ]
 
 [[package]]
@@ -1272,16 +1262,6 @@
 
 [[package]]
 name = "home"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff"
-dependencies = [
- "scopeguard 0.3.3",
- "winapi 0.3.6",
-]
-
-[[package]]
-name = "home"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3"
@@ -1299,9 +1279,9 @@
  "log",
  "mac",
  "markup5ever",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
 ]
 
 [[package]]
@@ -1540,10 +1520,29 @@
 checksum = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be"
 
 [[package]]
-name = "jsonrpc-core"
-version = "12.0.0"
+name = "jsonrpc-client-transports"
+version = "13.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "288dca7f9713710a29e485076b9340156cb701edb46a881f5d0c31aa4f5b9143"
+checksum = "39577db48b004cffb4c5b8e5c9b993c177c52599ecbee88711e815acf65144db"
+dependencies = [
+ "failure",
+ "futures",
+ "jsonrpc-core",
+ "jsonrpc-pubsub",
+ "jsonrpc-server-utils",
+ "log",
+ "parity-tokio-ipc",
+ "serde",
+ "serde_json",
+ "tokio",
+ "url 1.7.2",
+]
+
+[[package]]
+name = "jsonrpc-core"
+version = "13.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd42951eb35079520ee29b7efbac654d85821b397ef88c8151600ef7e2d00217"
 dependencies = [
  "futures",
  "log",
@@ -1553,6 +1552,70 @@
 ]
 
 [[package]]
+name = "jsonrpc-core-client"
+version = "13.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f047c10738edee7c3c6acf5241a0ce33df32ef9230c1a7fb03e4a77ee72c992f"
+dependencies = [
+ "jsonrpc-client-transports",
+]
+
+[[package]]
+name = "jsonrpc-derive"
+version = "13.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29f9149f785deaae92a4c834a9a1a83a4313b8cfedccf15362cd4cf039a64501"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
+]
+
+[[package]]
+name = "jsonrpc-ipc-server"
+version = "13.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "256c5e4292c17b4c2ecdf542299dc8e9d6b3939c075c54825570ad9317fe5751"
+dependencies = [
+ "jsonrpc-core",
+ "jsonrpc-server-utils",
+ "log",
+ "parity-tokio-ipc",
+ "parking_lot 0.9.0",
+ "tokio-service",
+]
+
+[[package]]
+name = "jsonrpc-pubsub"
+version = "13.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2c08b444cc0ed70263798834343d0ac875e664257df8079160f23ac1ea79446"
+dependencies = [
+ "jsonrpc-core",
+ "log",
+ "parking_lot 0.9.0",
+ "serde",
+]
+
+[[package]]
+name = "jsonrpc-server-utils"
+version = "13.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44561bfdd31401bad790527f1e951dde144f2341ddc3e1b859d32945e1a34eff"
+dependencies = [
+ "bytes",
+ "globset",
+ "jsonrpc-core",
+ "lazy_static 1.3.0",
+ "log",
+ "num_cpus",
+ "tokio",
+ "tokio-codec",
+ "unicase 2.4.0",
+]
+
+[[package]]
 name = "kernel32-sys"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1582,9 +1645,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.61"
+version = "0.2.62"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c665266eb592905e8503ba3403020f4b8794d26263f412ca33171600eca9a6fa"
+checksum = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -1667,6 +1730,15 @@
 ]
 
 [[package]]
+name = "lock_api"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"
+dependencies = [
+ "scopeguard 1.0.0",
+]
+
+[[package]]
 name = "log"
 version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1697,18 +1769,15 @@
 
 [[package]]
 name = "lsp-types"
-version = "0.57.2"
+version = "0.60.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b62b77309737b1e262b3bbf37ff8faa740562c633b14702afe9be85dbcb6f88a"
+checksum = "fe3edefcd66dde1f7f1df706f46520a3c93adc5ca4bc5747da6621195e894efd"
 dependencies = [
  "bitflags",
- "num-derive",
- "num-traits",
  "serde",
- "serde_derive",
  "serde_json",
- "url 1.7.2",
- "url_serde",
+ "serde_repr",
+ "url 2.1.0",
 ]
 
 [[package]]
@@ -1773,7 +1842,7 @@
  "chrono",
  "clap",
  "elasticlunr-rs",
- "env_logger 0.6.0",
+ "env_logger",
  "error-chain",
  "handlebars",
  "itertools 0.8.0",
@@ -1798,7 +1867,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "77d1f0ba4d1e6b86fa18e8853d026d7d76a97eb7eb5eb052ed80901e43b7fc10"
 dependencies = [
- "env_logger 0.6.0",
+ "env_logger",
  "failure",
  "log",
  "mdbook",
@@ -1811,7 +1880,7 @@
  "serde",
  "serde_derive",
  "serde_json",
- "structopt",
+ "structopt 0.2.18",
  "url 1.7.2",
 ]
 
@@ -1991,12 +2060,12 @@
  "colored",
  "compiletest_rs",
  "directories",
- "env_logger 0.6.0",
+ "env_logger",
  "getrandom",
  "hex",
  "log",
  "num-traits",
- "rand 0.6.1",
+ "rand 0.7.0",
  "rustc-workspace-hack",
  "rustc_version",
  "shell-escape",
@@ -2045,18 +2114,6 @@
 checksum = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 
 [[package]]
-name = "num-derive"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d"
-dependencies = [
- "num-traits",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "num-integer"
 version = "0.1.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2081,6 +2138,12 @@
 ]
 
 [[package]]
+name = "once_cell"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0"
+
+[[package]]
 name = "open"
 version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2117,9 +2180,9 @@
 
 [[package]]
 name = "openssl-src"
-version = "111.3.0+1.1.1c"
+version = "111.6.0+1.1.1d"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53ed5f31d294bdf5f7a4ba0a206c2754b0f60e9a63b7e3076babc5317873c797"
+checksum = "b9c2da1de8a7a3f860919c01540b03a6db16de042405a8a07a5e9d0b4b825d9c"
 dependencies = [
  "cc",
 ]
@@ -2190,13 +2253,42 @@
 ]
 
 [[package]]
+name = "parity-tokio-ipc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8281bf4f1d6429573f89589bf68d89451c46750977a8264f8ea3edbabeba7947"
+dependencies = [
+ "bytes",
+ "futures",
+ "log",
+ "mio-named-pipes",
+ "miow 0.3.3",
+ "rand 0.7.0",
+ "tokio",
+ "tokio-named-pipes",
+ "tokio-uds",
+ "winapi 0.3.6",
+]
+
+[[package]]
 name = "parking_lot"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
 dependencies = [
- "lock_api",
- "parking_lot_core",
+ "lock_api 0.1.3",
+ "parking_lot_core 0.4.0",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
+dependencies = [
+ "lock_api 0.3.1",
+ "parking_lot_core 0.6.2",
+ "rustc_version",
 ]
 
 [[package]]
@@ -2213,6 +2305,21 @@
 ]
 
 [[package]]
+name = "parking_lot_core"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
+dependencies = [
+ "cfg-if",
+ "cloudabi",
+ "libc",
+ "redox_syscall",
+ "rustc_version",
+ "smallvec",
+ "winapi 0.3.6",
+]
+
+[[package]]
 name = "percent-encoding"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2251,9 +2358,9 @@
 dependencies = [
  "pest",
  "pest_meta",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
 ]
 
 [[package]]
@@ -2324,9 +2431,9 @@
 
 [[package]]
 name = "polonius-engine"
-version = "0.9.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6b8a5defa2aef9ba4999aaa745fbc01c622ecea35964a306adc3e44be4f3b5b"
+checksum = "50fa9dbfd0d3d60594da338cfe6f94028433eecae4b11b7e83fd99759227bbfe"
 dependencies = [
  "datafrog",
  "log",
@@ -2362,17 +2469,46 @@
 checksum = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61"
 dependencies = [
  "chrono",
- "env_logger 0.6.0",
+ "env_logger",
  "log",
 ]
 
 [[package]]
+name = "proc-macro-crate"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e"
+dependencies = [
+ "toml",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097"
+dependencies = [
+ "proc-macro2 1.0.3",
+ "quote 1.0.2",
+ "syn 1.0.5",
+]
+
+[[package]]
 name = "proc-macro2"
 version = "0.4.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
 dependencies = [
- "unicode-xid",
+ "unicode-xid 0.1.0",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8"
+dependencies = [
+ "unicode-xid 0.2.0",
 ]
 
 [[package]]
@@ -2427,19 +2563,28 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
 dependencies = [
- "proc-macro2",
+ "proc-macro2 0.4.30",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+dependencies = [
+ "proc-macro2 1.0.3",
 ]
 
 [[package]]
 name = "racer"
-version = "2.1.25"
+version = "2.1.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0727b9d7baaf9e42851145545d7b980b5c1752bd16a4c77c925c5e573d0069d9"
+checksum = "dde22b84ab75220015cbd91240222402bf885cbe3a5dc856475771abb82533ae"
 dependencies = [
  "bitflags",
  "clap",
  "derive_more",
- "env_logger 0.6.0",
+ "env_logger",
  "humantime",
  "lazy_static 1.3.0",
  "log",
@@ -2726,18 +2871,18 @@
 
 [[package]]
 name = "rls"
-version = "1.38.0"
+version = "1.39.0"
 dependencies = [
  "cargo",
  "cargo_metadata",
  "clippy_lints",
  "crossbeam-channel",
  "difference",
- "env_logger 0.6.0",
+ "env_logger",
  "failure",
  "futures",
  "heck",
- "home 0.3.3",
+ "home",
  "itertools 0.8.0",
  "jsonrpc-core",
  "lazy_static 1.3.0",
@@ -2752,6 +2897,7 @@
  "regex",
  "rls-analysis",
  "rls-data",
+ "rls-ipc",
  "rls-rustc",
  "rls-span",
  "rls-vfs",
@@ -2761,14 +2907,14 @@
  "rustfmt-nightly",
  "serde",
  "serde_derive",
- "serde_ignored 0.0.4",
+ "serde_ignored",
  "serde_json",
  "tempfile",
  "tokio",
  "tokio-process",
  "tokio-timer",
  "toml",
- "url 1.7.2",
+ "url 2.1.0",
  "walkdir",
 ]
 
@@ -2800,8 +2946,32 @@
 ]
 
 [[package]]
+name = "rls-ipc"
+version = "0.1.0"
+dependencies = [
+ "jsonrpc-core",
+ "jsonrpc-core-client",
+ "jsonrpc-derive",
+ "jsonrpc-ipc-server",
+ "rls-data",
+ "serde",
+]
+
+[[package]]
 name = "rls-rustc"
 version = "0.6.0"
+dependencies = [
+ "clippy_lints",
+ "env_logger",
+ "failure",
+ "futures",
+ "log",
+ "rand 0.6.1",
+ "rls-data",
+ "rls-ipc",
+ "serde",
+ "tokio",
+]
 
 [[package]]
 name = "rls-span"
@@ -2844,11 +3014,10 @@
  "fmt_macros",
  "graphviz",
  "jobserver",
- "lazy_static 1.3.0",
  "log",
  "measureme",
  "num_cpus",
- "parking_lot",
+ "parking_lot 0.9.0",
  "polonius-engine",
  "rustc-rayon",
  "rustc-rayon-core",
@@ -2867,9 +3036,9 @@
 
 [[package]]
 name = "rustc-ap-arena"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dc2e1e68b64268c543bfa6e63e3c0d9ea58074c71396f42f76931f35a9287f9"
+checksum = "f59b76d334bd533f3fdc5c651c27678c5e80fac67c6f7da22ba21a58878c55f5"
 dependencies = [
  "rustc-ap-rustc_data_structures",
  "smallvec",
@@ -2877,15 +3046,15 @@
 
 [[package]]
 name = "rustc-ap-graphviz"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c108d647ce0dd46477b048eafff5a6273b5652e02d47424b0cd684147379c811"
+checksum = "3e632ef08ca17458acfd46d2ead3d541a1c249586cd5329f5fe333dacfab6142"
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "656771744e0783cb8e4481e3b8b1f975687610aaf18833b898018111a0e0e582"
+checksum = "e89e2c7be68185418f3cd56af3df8b29007a59a1cebefa63612d055f9bcb1a36"
 dependencies = [
  "cfg-if",
  "crossbeam-utils 0.6.5",
@@ -2894,7 +3063,7 @@
  "jobserver",
  "lazy_static 1.3.0",
  "log",
- "parking_lot",
+ "parking_lot 0.7.1",
  "rustc-ap-graphviz",
  "rustc-ap-serialize",
  "rustc-hash",
@@ -2906,9 +3075,9 @@
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e37064f6624bc799bfaa2968b61ee6880926dea2a8bba69f18aef6c8e69c9604"
+checksum = "1e47cb380abeb72b01e42b2342d592f7eeea7d536c2f1f0d0e550dc509e46333"
 dependencies = [
  "annotate-snippets",
  "atty",
@@ -2916,34 +3085,38 @@
  "rustc-ap-rustc_data_structures",
  "rustc-ap-serialize",
  "rustc-ap-syntax_pos",
+ "term_size",
  "termcolor",
  "unicode-width",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_lexer"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef5bc0a971823637ea23a857f0ef1467f44b1e05d71968821f83a0abe53e0fe3"
+checksum = "494cfaf67f49217d67d0774eeecbba61ac89acf478db97ef11f113ed8a959305"
+dependencies = [
+ "unicode-xid 0.2.0",
+]
 
 [[package]]
 name = "rustc-ap-rustc_macros"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b90037e3336fe8835f468db44d0848ae10d9cc8533ae89b55828883f905b7e80"
+checksum = "e2e5d36becc59b4497f9cbd3ae0610081de0207a1d0e95c066369167b14f486f"
 dependencies = [
  "itertools 0.8.0",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
  "synstructure",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cadf9ca07315eab3a7a21f63872f9cc81e250fd6ede0419c24f8926ade73a45d"
+checksum = "a7bfc5f96dfc3b9f8d5b57884f7f37467ecff6776cd4b8b491a7daece6fdd7c2"
 dependencies = [
  "bitflags",
  "log",
@@ -2954,9 +3127,9 @@
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61673783f2089e01033ffa82d1988f55175402071b31253a358292e1624d4602"
+checksum = "2bb9ee231cf79eded39c56647499f83d6136ff5c8c0baaa9e21b6febee00f4f6"
 dependencies = [
  "indexmap",
  "smallvec",
@@ -2964,9 +3137,9 @@
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28f3dd1346d5b0269c07a4a78855e309a298ab569c9c1302d4d4f57f8eee4e84"
+checksum = "b3827fc208814efbde82d613e31d11b4250ce9e8cf8afe4a4d47bbbd099632c9"
 dependencies = [
  "bitflags",
  "lazy_static 1.3.0",
@@ -2984,9 +3157,9 @@
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "546.0.0"
+version = "583.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45e67b526dbda3a0c7dab91c8947d43685e7697f52686a4949da3c179cd7c979"
+checksum = "930ed81c34f325e512cc315c04d676fa84a373879d5c43bb54054a0522b05213"
 dependencies = [
  "cfg-if",
  "rustc-ap-arena",
@@ -3057,21 +3230,21 @@
 
 [[package]]
 name = "rustc-std-workspace-alloc"
-version = "1.0.0"
+version = "1.99.0"
 dependencies = [
  "alloc",
 ]
 
 [[package]]
 name = "rustc-std-workspace-core"
-version = "1.0.0"
+version = "1.99.0"
 dependencies = [
  "core",
 ]
 
 [[package]]
 name = "rustc-std-workspace-std"
-version = "1.0.0"
+version = "1.99.0"
 dependencies = [
  "std",
 ]
@@ -3080,15 +3253,10 @@
 name = "rustc-workspace-hack"
 version = "1.0.0"
 dependencies = [
- "byteorder",
  "crossbeam-utils 0.6.5",
- "parking_lot",
- "rand 0.6.1",
- "scopeguard 0.3.3",
  "serde",
  "serde_json",
  "smallvec",
- "syn",
  "winapi 0.3.6",
 ]
 
@@ -3128,11 +3296,7 @@
 name = "rustc_codegen_llvm"
 version = "0.0.0"
 dependencies = [
- "cc",
- "memmap",
- "num_cpus",
  "rustc_llvm",
- "tempfile",
 ]
 
 [[package]]
@@ -3146,7 +3310,7 @@
  "log",
  "memmap",
  "num_cpus",
- "parking_lot",
+ "parking_lot 0.9.0",
  "rustc",
  "rustc_apfloat",
  "rustc_codegen_utils",
@@ -3189,7 +3353,7 @@
  "jobserver",
  "lazy_static 1.3.0",
  "log",
- "parking_lot",
+ "parking_lot 0.9.0",
  "rustc-hash",
  "rustc-rayon",
  "rustc-rayon-core",
@@ -3202,8 +3366,9 @@
 name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
- "env_logger 0.5.13",
+ "env_logger",
  "graphviz",
+ "lazy_static 1.3.0",
  "log",
  "rustc",
  "rustc_ast_borrowck",
@@ -3247,7 +3412,7 @@
 dependencies = [
  "graphviz",
  "log",
- "rand 0.6.1",
+ "rand 0.7.0",
  "rustc",
  "rustc_data_structures",
  "rustc_fs_util",
@@ -3261,6 +3426,7 @@
 version = "0.0.0"
 dependencies = [
  "log",
+ "once_cell",
  "rustc",
  "rustc-rayon",
  "rustc_ast_borrowck",
@@ -3290,7 +3456,7 @@
 name = "rustc_lexer"
 version = "0.1.0"
 dependencies = [
- "unicode-xid",
+ "unicode-xid 0.2.0",
 ]
 
 [[package]]
@@ -3329,9 +3495,9 @@
 version = "0.1.0"
 dependencies = [
  "itertools 0.8.0",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
  "synstructure",
 ]
 
@@ -3368,6 +3534,7 @@
  "rustc_apfloat",
  "rustc_data_structures",
  "rustc_errors",
+ "rustc_lexer",
  "rustc_target",
  "serialize",
  "smallvec",
@@ -3569,26 +3736,25 @@
 
 [[package]]
 name = "rustfmt-config_proc_macro"
-version = "0.1.2"
+version = "0.2.0"
 dependencies = [
- "proc-macro2",
- "quote",
+ "proc-macro2 1.0.3",
+ "quote 1.0.2",
  "serde",
- "syn",
+ "syn 1.0.5",
 ]
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.5"
+version = "1.4.8"
 dependencies = [
  "annotate-snippets",
- "atty",
  "bytecount",
  "cargo_metadata",
  "derive-new",
  "diff",
  "dirs",
- "env_logger 0.6.0",
+ "env_logger",
  "failure",
  "getopts",
  "ignore",
@@ -3603,7 +3769,7 @@
  "rustfmt-config_proc_macro",
  "serde",
  "serde_json",
- "structopt",
+ "structopt 0.3.1",
  "term 0.6.0",
  "toml",
  "unicode-segmentation",
@@ -3712,18 +3878,9 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_ignored"
-version = "0.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
-dependencies = [
- "serde",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
 ]
 
 [[package]]
@@ -3747,6 +3904,17 @@
 ]
 
 [[package]]
+name = "serde_repr"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573"
+dependencies = [
+ "proc-macro2 1.0.3",
+ "quote 1.0.2",
+ "syn 1.0.5",
+]
+
+[[package]]
 name = "serde_urlencoded"
 version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3862,12 +4030,13 @@
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
- "rand 0.6.1",
+ "rand 0.7.0",
  "rustc_asan",
  "rustc_lsan",
  "rustc_msan",
  "rustc_tsan",
  "unwind",
+ "wasi",
 ]
 
 [[package]]
@@ -3902,8 +4071,8 @@
 dependencies = [
  "phf_generator",
  "phf_shared",
- "proc-macro2",
- "quote",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
  "string_cache_shared",
 ]
 
@@ -3924,9 +4093,9 @@
 
 [[package]]
 name = "strsim"
-version = "0.7.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "structopt"
@@ -3935,7 +4104,17 @@
 checksum = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7"
 dependencies = [
  "clap",
- "structopt-derive",
+ "structopt-derive 0.2.18",
+]
+
+[[package]]
+name = "structopt"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ac9d6e93dd792b217bf89cda5c14566e3043960c6f9da890c2ba5d09d07804c"
+dependencies = [
+ "clap",
+ "structopt-derive 0.3.1",
 ]
 
 [[package]]
@@ -3945,9 +4124,22 @@
 checksum = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107"
 dependencies = [
  "heck",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ae9e5165d463a0dea76967d021f8d0f9316057bf5163aa2a4843790e842ff37"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2 1.0.3",
+ "quote 1.0.2",
+ "syn 1.0.5",
 ]
 
 [[package]]
@@ -3963,9 +4155,9 @@
 checksum = "8baacebd7b7c9b864d83a6ba7a246232983e277b86fa5cdec77f565715a4b136"
 dependencies = [
  "heck",
- "proc-macro2",
- "quote",
- "syn",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
 ]
 
 [[package]]
@@ -3974,9 +4166,20 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3"
 dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "unicode-xid 0.1.0",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
+dependencies = [
+ "proc-macro2 1.0.3",
+ "quote 1.0.2",
+ "unicode-xid 0.2.0",
 ]
 
 [[package]]
@@ -3985,10 +4188,10 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "unicode-xid",
+ "proc-macro2 0.4.30",
+ "quote 0.6.12",
+ "syn 0.15.35",
+ "unicode-xid 0.1.0",
 ]
 
 [[package]]
@@ -4017,6 +4220,7 @@
  "log",
  "rustc_data_structures",
  "rustc_errors",
+ "rustc_lexer",
  "rustc_target",
  "smallvec",
  "syntax",
@@ -4056,13 +4260,13 @@
 
 [[package]]
 name = "tempfile"
-version = "3.0.5"
+version = "3.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
+checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
 dependencies = [
  "cfg-if",
  "libc",
- "rand 0.6.1",
+ "rand 0.7.0",
  "redox_syscall",
  "remove_dir_all",
  "winapi 0.3.6",
@@ -4166,9 +4370,9 @@
 
 [[package]]
 name = "textwrap"
-version = "0.10.0"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
 dependencies = [
  "unicode-width",
 ]
@@ -4292,6 +4496,19 @@
 ]
 
 [[package]]
+name = "tokio-named-pipes"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d282d483052288b2308ba5ee795f5673b159c9bdf63c385a05609da782a5eae"
+dependencies = [
+ "bytes",
+ "futures",
+ "mio",
+ "mio-named-pipes",
+ "tokio",
+]
+
+[[package]]
 name = "tokio-process"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4319,13 +4536,22 @@
  "log",
  "mio",
  "num_cpus",
- "parking_lot",
+ "parking_lot 0.7.1",
  "slab",
  "tokio-executor",
  "tokio-io",
 ]
 
 [[package]]
+name = "tokio-service"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
+dependencies = [
+ "futures",
+]
+
+[[package]]
 name = "tokio-signal"
 version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4448,8 +4674,8 @@
 checksum = "3c99ca245ec273c7e75c8ee58f47b882d0146f3c2c8495158082c6671e8b5335"
 dependencies = [
  "darling",
- "quote",
- "syn",
+ "quote 0.6.12",
+ "syn 0.15.35",
 ]
 
 [[package]]
@@ -4533,6 +4759,12 @@
 checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 
 [[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+
+[[package]]
 name = "unicode_categories"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4581,16 +4813,6 @@
 ]
 
 [[package]]
-name = "url_serde"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
-dependencies = [
- "serde",
- "url 1.7.2",
-]
-
-[[package]]
 name = "utf-8"
 version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4678,6 +4900,17 @@
 ]
 
 [[package]]
+name = "wasi"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
+dependencies = [
+ "compiler_builtins",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
+]
+
+[[package]]
 name = "winapi"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/README.md b/README.md
index 2df9e6a..96d7e93 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,7 @@
    * `cmake` 3.4.3 or later
    * `curl`
    * `git`
+   * `ssl` which comes in `libssl-dev` or `openssl-devel`
 
 2. Clone the [source] with `git`:
 
@@ -56,6 +57,8 @@
     an installation (using `./x.py install`) that you set the `prefix` value
     in the `[install]` section to a directory that you have write permissions.
 
+    Create install directory if you are not installing in default directory
+
 4. Build and install:
 
     ```sh
diff --git a/RELEASES.md b/RELEASES.md
index f26f6e6..d634feb 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,108 @@
+Version 1.38.0 (2019-09-26)
+==========================
+
+Language
+--------
+- [The `#[global_allocator]` attribute can now be used in submodules.][62735]
+- [The `#[deprecated]` attribute can now be used on macros.][62042]
+
+Compiler
+--------
+- [Added pipelined compilation support to `rustc`.][62766] This will
+  improve compilation times in some cases. For further information please refer
+  to the [_"Evaluating pipelined rustc compilation"_][pipeline-internals] thread.
+- [Added tier 3\* support for the `aarch64-uwp-windows-msvc`, `i686-uwp-windows-gnu`,
+  `i686-uwp-windows-msvc`, `x86_64-uwp-windows-gnu`, and
+  `x86_64-uwp-windows-msvc` targets.][60260]
+- [Added tier 3 support for the `armv7-unknown-linux-gnueabi` and
+  `armv7-unknown-linux-musleabi` targets.][63107]
+- [Added tier 3 support for the `hexagon-unknown-linux-musl` target.][62814]
+- [Added tier 3 support for the `riscv32i-unknown-none-elf` target.][62784]
+
+\* Refer to Rust's [platform support page][forge-platform-support] for more
+information on Rust's tiered platform support.
+
+Libraries
+---------
+- [`ascii::EscapeDefault` now implements `Clone` and `Display`.][63421]
+- [Derive macros for prelude traits (e.g. `Clone`, `Debug`, `Hash`) are now
+  available at the same path as the trait.][63056] (e.g. The `Clone` derive macro
+  is available at `std::clone::Clone`). This also makes all built-in macros
+  available in `std`/`core` root. e.g. `std::include_bytes!`.
+- [`str::Chars` now implements `Debug`.][63000]
+- [`slice::{concat, connect, join}` now accepts `&[T]` in addition to `&T`.][62528]
+- [`*const T` and `*mut T` now implement `marker::Unpin`.][62583]
+- [`Arc<[T]>` and `Rc<[T]>` now implement `FromIterator<T>`.][61953]
+- [Added euclidean remainder and division operations (`div_euclid`,
+  `rem_euclid`) to all numeric primitives.][61884] Additionally `checked`,
+  `overflowing`, and `wrapping` versions are available for all
+  integer primitives.
+- [`thread::AccessError` now implements `Clone`, `Copy`, `Eq`, `Error`, and
+  `PartialEq`.][61491]
+- [`iter::{StepBy, Peekable, Take}` now implement `DoubleEndedIterator`.][61457]
+
+Stabilized APIs
+---------------
+- [`<*const T>::cast`]
+- [`<*mut T>::cast`]
+- [`Duration::as_secs_f32`]
+- [`Duration::as_secs_f64`]
+- [`Duration::div_duration_f32`]
+- [`Duration::div_duration_f64`]
+- [`Duration::div_f32`]
+- [`Duration::div_f64`]
+- [`Duration::from_secs_f32`]
+- [`Duration::from_secs_f64`]
+- [`Duration::mul_f32`]
+- [`Duration::mul_f64`]
+- [`any::type_name`]
+
+Cargo
+-----
+- [Added pipelined compilation support to `cargo`.][cargo/7143]
+- [You can now pass the `--features` option multiple times to enable
+  multiple features.][cargo/7084]
+
+Misc
+----
+- [`rustc` will now warn about some incorrect uses of
+  `mem::{uninitialized, zeroed}` that are known to cause undefined behaviour.][63346]
+
+[60260]: https://github.com/rust-lang/rust/pull/60260/
+[61457]: https://github.com/rust-lang/rust/pull/61457/
+[61491]: https://github.com/rust-lang/rust/pull/61491/
+[61884]: https://github.com/rust-lang/rust/pull/61884/
+[61953]: https://github.com/rust-lang/rust/pull/61953/
+[62042]: https://github.com/rust-lang/rust/pull/62042/
+[62528]: https://github.com/rust-lang/rust/pull/62528/
+[62583]: https://github.com/rust-lang/rust/pull/62583/
+[62735]: https://github.com/rust-lang/rust/pull/62735/
+[62766]: https://github.com/rust-lang/rust/pull/62766/
+[62784]: https://github.com/rust-lang/rust/pull/62784/
+[62814]: https://github.com/rust-lang/rust/pull/62814/
+[63000]: https://github.com/rust-lang/rust/pull/63000/
+[63056]: https://github.com/rust-lang/rust/pull/63056/
+[63107]: https://github.com/rust-lang/rust/pull/63107/
+[63346]: https://github.com/rust-lang/rust/pull/63346/
+[63421]: https://github.com/rust-lang/rust/pull/63421/
+[cargo/7084]: https://github.com/rust-lang/cargo/pull/7084/
+[cargo/7143]: https://github.com/rust-lang/cargo/pull/7143/
+[`<*const T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
+[`<*mut T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
+[`Duration::as_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f32
+[`Duration::as_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f64
+[`Duration::div_duration_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f32
+[`Duration::div_duration_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f64
+[`Duration::div_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f32
+[`Duration::div_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f64
+[`Duration::from_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f32
+[`Duration::from_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f64
+[`Duration::mul_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f32
+[`Duration::mul_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f64
+[`any::type_name`]: https://doc.rust-lang.org/std/any/fn.type_name.html
+[forge-platform-support]: https://forge.rust-lang.org/platform-support.html
+[pipeline-internals]: https://internals.rust-lang.org/t/evaluating-pipelined-rustc-compilation/10199
+
 Version 1.37.0 (2019-08-15)
 ==========================
 
diff --git a/config.toml.example b/config.toml.example
index 30e2ee1..848147c 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -184,7 +184,7 @@
 # default.
 #extended = false
 
-# Installs chosen set of extended tools if enables. By default builds all.
+# Installs chosen set of extended tools if enabled. By default builds all.
 # If chosen tool failed to build the installation fails.
 #tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"]
 
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 8cb48df..84415ba 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -119,17 +119,18 @@
         cmd.arg(format!("-Cdebuginfo={}", debuginfo_level));
     }
 
-    if env::var_os("RUSTC_DENY_WARNINGS").is_some() &&
-       env::var_os("RUSTC_EXTERNAL_TOOL").is_none() {
+    if env::var_os("RUSTC_EXTERNAL_TOOL").is_none() {
         // When extending this list, add the new lints to the RUSTFLAGS of the
         // build_bootstrap function of src/bootstrap/bootstrap.py as well as
         // some code doesn't go through this `rustc` wrapper.
-        cmd.arg("-Dwarnings");
-        cmd.arg("-Drust_2018_idioms");
-        cmd.arg("-Dunused_lifetimes");
+        cmd.arg("-Wrust_2018_idioms");
+        cmd.arg("-Wunused_lifetimes");
         if use_internal_lints(crate_name) {
             cmd.arg("-Zunstable-options");
-            cmd.arg("-Drustc::internal");
+            cmd.arg("-Wrustc::internal");
+        }
+        if env::var_os("RUSTC_DENY_WARNINGS").is_some() {
+            cmd.arg("-Dwarnings");
         }
     }
 
diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs
index 766a346..a13ff69 100644
--- a/src/bootstrap/bin/rustdoc.rs
+++ b/src/bootstrap/bin/rustdoc.rs
@@ -5,6 +5,7 @@
 use std::env;
 use std::process::Command;
 use std::path::PathBuf;
+use std::ffi::OsString;
 
 fn main() {
     let args = env::args_os().skip(1).collect::<Vec<_>>();
@@ -44,7 +45,9 @@
         cmd.arg("-Z").arg("force-unstable-if-unmarked");
     }
     if let Some(linker) = env::var_os("RUSTC_TARGET_LINKER") {
-        cmd.arg("--linker").arg(linker).arg("-Z").arg("unstable-options");
+        let mut arg = OsString::from("-Clinker=");
+        arg.push(&linker);
+        cmd.arg(arg);
     }
 
     // Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 4162fe1..65129ee 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -523,6 +523,10 @@
         'value2'
         >>> rb.get_toml('key', 'c') is None
         True
+
+        >>> rb.config_toml = 'key1 = true'
+        >>> rb.get_toml("key1")
+        'true'
         """
 
         cur_section = None
@@ -571,6 +575,12 @@
 
         >>> RustBuild.get_string('    "devel"   ')
         'devel'
+        >>> RustBuild.get_string("    'devel'   ")
+        'devel'
+        >>> RustBuild.get_string('devel') is None
+        True
+        >>> RustBuild.get_string('    "devel   ')
+        ''
         """
         start = line.find('"')
         if start != -1:
@@ -631,8 +641,9 @@
         target_linker = self.get_toml("linker", build_section)
         if target_linker is not None:
             env["RUSTFLAGS"] += "-C linker=" + target_linker + " "
+        env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes "
         if self.get_toml("deny-warnings", "rust") != "false":
-            env["RUSTFLAGS"] += "-Dwarnings -Drust_2018_idioms -Dunused_lifetimes "
+            env["RUSTFLAGS"] += "-Dwarnings "
 
         env["PATH"] = os.path.join(self.bin_root(), "bin") + \
             os.pathsep + env["PATH"]
@@ -668,7 +679,7 @@
     def update_submodule(self, module, checked_out, recorded_submodules):
         module_path = os.path.join(self.rust_root, module)
 
-        if checked_out != None:
+        if checked_out is not None:
             default_encoding = sys.getdefaultencoding()
             checked_out = checked_out.communicate()[0].decode(default_encoding).strip()
             if recorded_submodules[module] == checked_out:
@@ -697,6 +708,14 @@
         if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \
                 self.get_toml('submodules') == "false":
             return
+
+        # check the existence of 'git' command
+        try:
+            subprocess.check_output(['git', '--version'])
+        except (subprocess.CalledProcessError, OSError):
+            print("error: `git` is not found, please make sure it's installed and in the path.")
+            sys.exit(1)
+
         slow_submodules = self.get_toml('fast-submodules') == "false"
         start_time = time()
         if slow_submodules:
@@ -821,13 +840,13 @@
     except (OSError, IOError):
         pass
 
-    match = re.search(r'\nverbose = (\d+)', build.config_toml)
-    if match is not None:
-        build.verbose = max(build.verbose, int(match.group(1)))
+    config_verbose = build.get_toml('verbose', 'build')
+    if config_verbose is not None:
+        build.verbose = max(build.verbose, int(config_verbose))
 
-    build.use_vendored_sources = '\nvendor = true' in build.config_toml
+    build.use_vendored_sources = build.get_toml('vendor', 'build') == 'true'
 
-    build.use_locked_deps = '\nlocked-deps = true' in build.config_toml
+    build.use_locked_deps = build.get_toml('locked-deps', 'build') == 'true'
 
     build.check_vendored_status()
 
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 4f5de1e..b7873fd 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1167,6 +1167,8 @@
             cargo.arg("--frozen");
         }
 
+        cargo.env("RUSTC_INSTALL_BINDIR", &self.config.bindir);
+
         self.ci_env.force_coloring_in_ci(&mut cargo);
 
         cargo
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 9d57a4f..9a96445 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -212,6 +212,7 @@
                 emscripten: false,
             });
             cargo.env("LLVM_CONFIG", llvm_config);
+            cargo.env("RUSTC_BUILD_SANITIZERS", "1");
         }
 
         cargo.arg("--features").arg(features)
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 43d9264..52b5cd8 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -137,7 +137,7 @@
     pub sysconfdir: Option<PathBuf>,
     pub datadir: Option<PathBuf>,
     pub docdir: Option<PathBuf>,
-    pub bindir: Option<PathBuf>,
+    pub bindir: PathBuf,
     pub libdir: Option<PathBuf>,
     pub mandir: Option<PathBuf>,
     pub codegen_tests: bool,
@@ -400,6 +400,7 @@
         config.incremental = flags.incremental;
         config.dry_run = flags.dry_run;
         config.keep_stage = flags.keep_stage;
+        config.bindir = "bin".into(); // default
         if let Some(value) = flags.deny_warnings {
             config.deny_warnings = value;
         }
@@ -482,7 +483,7 @@
             config.sysconfdir = install.sysconfdir.clone().map(PathBuf::from);
             config.datadir = install.datadir.clone().map(PathBuf::from);
             config.docdir = install.docdir.clone().map(PathBuf::from);
-            config.bindir = install.bindir.clone().map(PathBuf::from);
+            set(&mut config.bindir, install.bindir.clone().map(PathBuf::from));
             config.libdir = install.libdir.clone().map(PathBuf::from);
             config.mandir = install.mandir.clone().map(PathBuf::from);
         }
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 0f4ac63..076bcd8 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -808,6 +808,7 @@
             "llvm-project/lld", "llvm-project\\lld",
             "llvm-project/lldb", "llvm-project\\lldb",
             "llvm-project/llvm", "llvm-project\\llvm",
+            "llvm-project/compiler-rt", "llvm-project\\compiler-rt",
         ];
         if spath.contains("llvm-project") && !spath.ends_with("llvm-project")
             && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
@@ -1999,6 +2000,8 @@
     }
 
     fn run(self, builder: &Builder<'_>) {
+        // This gets called by `promote-release`
+        // (https://github.com/rust-lang/rust-central-station/tree/master/promote-release).
         let mut cmd = builder.tool_cmd(Tool::BuildManifest);
         if builder.config.dry_run {
             return;
@@ -2009,10 +2012,14 @@
         let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
             panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
         });
-        let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
-            panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
-        });
-        let pass = t!(fs::read_to_string(&file));
+        let pass = if env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err() {
+            let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
+                panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
+            });
+            t!(fs::read_to_string(&file))
+        } else {
+            String::new()
+        };
 
         let today = output(Command::new("date").arg("+%Y-%m-%d"));
 
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 3d0a175..6faedc8 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -375,7 +375,7 @@
                up_to_date(&footer, &html) &&
                up_to_date(&favicon, &html) &&
                up_to_date(&full_toc, &html) &&
-               up_to_date(&version_info, &html) &&
+               (builder.config.dry_run || up_to_date(&version_info, &html)) &&
                (builder.config.dry_run || up_to_date(&rustdoc, &html)) {
                 continue
             }
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 828865f..d9580b5 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -36,7 +36,7 @@
     // This overrides the deny-warnings configuation option,
     // which passes -Dwarnings to the compiler invocations.
     //
-    // true => deny, false => allow
+    // true => deny, false => warn
     pub deny_warnings: Option<bool>,
 }
 
@@ -556,10 +556,10 @@
 fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> {
     match matches.opt_str("warnings").as_ref().map(|v| v.as_str()) {
         Some("deny") => Some(true),
-        Some("allow") => Some(false),
+        Some("warn") => Some(false),
         Some(value) => {
             eprintln!(
-                r#"invalid value for --warnings: {:?}, expected "allow" or "deny""#,
+                r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#,
                 value,
                 );
             process::exit(1);
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 5575867..384219c 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -67,7 +67,6 @@
     let sysconfdir_default = PathBuf::from("/etc");
     let datadir_default = PathBuf::from("share");
     let docdir_default = datadir_default.join("doc/rust");
-    let bindir_default = PathBuf::from("bin");
     let libdir_default = PathBuf::from("lib");
     let mandir_default = datadir_default.join("man");
     let prefix = builder.config.prefix.as_ref().map_or(prefix_default, |p| {
@@ -76,7 +75,7 @@
     let sysconfdir = builder.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
     let datadir = builder.config.datadir.as_ref().unwrap_or(&datadir_default);
     let docdir = builder.config.docdir.as_ref().unwrap_or(&docdir_default);
-    let bindir = builder.config.bindir.as_ref().unwrap_or(&bindir_default);
+    let bindir = &builder.config.bindir;
     let libdir = builder.config.libdir.as_ref().unwrap_or(&libdir_default);
     let mandir = builder.config.mandir.as_ref().unwrap_or(&mandir_default);
 
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index f02def3..7bf9ea2 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -81,26 +81,29 @@
             (info, "src/llvm-project/llvm", builder.llvm_out(target), dir.join("bin"))
         };
 
-        if !llvm_info.is_git() {
-            println!(
-                "git could not determine the LLVM submodule commit hash. \
-                Assuming that an LLVM build is necessary.",
-            );
-        }
-
         let build_llvm_config = llvm_config_ret_dir
             .join(exe("llvm-config", &*builder.config.build));
         let done_stamp = out_dir.join("llvm-finished-building");
 
-        if let Some(llvm_commit) = llvm_info.sha() {
-            if done_stamp.exists() {
+        if done_stamp.exists() {
+            if let Some(llvm_commit) = llvm_info.sha() {
                 let done_contents = t!(fs::read(&done_stamp));
 
                 // If LLVM was already built previously and the submodule's commit didn't change
                 // from the previous build, then no action is required.
                 if done_contents == llvm_commit.as_bytes() {
-                    return build_llvm_config
+                    return build_llvm_config;
                 }
+            } else {
+                builder.info(
+                    "Could not determine the LLVM submodule commit hash. \
+                     Assuming that an LLVM rebuild is not necessary.",
+                );
+                builder.info(&format!(
+                    "To force LLVM to rebuild, remove the file `{}`",
+                    done_stamp.display()
+                ));
+                return build_llvm_config;
             }
         }
 
@@ -303,9 +306,7 @@
 
         cfg.build();
 
-        if let Some(llvm_commit) = llvm_info.sha() {
-            t!(fs::write(&done_stamp, llvm_commit));
-        }
+        t!(fs::write(&done_stamp, llvm_info.sha().unwrap_or("")));
 
         build_llvm_config
     }
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 97b28ed..00d87f3 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1327,7 +1327,10 @@
             cmd.env("RUSTC_PROFILER_SUPPORT", "1");
         }
 
-        cmd.env("RUST_TEST_TMPDIR", builder.out.join("tmp"));
+        let tmp = builder.out.join("tmp");
+        std::fs::create_dir_all(&tmp).unwrap();
+        cmd.env("RUST_TEST_TMPDIR", tmp);
+
 
         cmd.arg("--adb-path").arg("adb");
         cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index 77c9cda..1656066 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -236,10 +236,16 @@
         MSYS_BITS: 32
         RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
         SCRIPT: make ci-subset-1
+        # FIXME(#59637)
+        NO_DEBUG_ASSERTIONS: 1
+        NO_LLVM_ASSERTIONS: 1
       i686-msvc-2:
         MSYS_BITS: 32
         RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
         SCRIPT: make ci-subset-2
+        # FIXME(#59637)
+        NO_DEBUG_ASSERTIONS: 1
+        NO_LLVM_ASSERTIONS: 1
       # MSVC aux tests
       x86_64-msvc-aux:
         MSYS_BITS: 64
@@ -250,6 +256,9 @@
         SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
         RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
         VCVARS_BAT: vcvars64.bat
+        # FIXME(#59637)
+        NO_DEBUG_ASSERTIONS: 1
+        NO_LLVM_ASSERTIONS: 1
       # MSVC tools tests
       x86_64-msvc-tools:
         MSYS_BITS: 64
diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml
index ac6b344..da0a899 100644
--- a/src/ci/azure-pipelines/steps/run.yml
+++ b/src/ci/azure-pipelines/steps/run.yml
@@ -147,8 +147,15 @@
     git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git
     cd rust-toolstate
     python2.7 "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" ""
+    # Only check maintainers if this build is supposed to publish toolstate.
+    # Builds that are not supposed to publish don't have the access token.
+    if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then
+      TOOLSTATE_VALIDATE_MAINTAINERS_REPO=rust-lang/rust python2.7 "${BUILD_SOURCESDIRECTORY}/src/tools/publish_toolstate.py"
+    fi
     cd ..
     rm -rf rust-toolstate
+  env:
+    TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN)
   condition: and(succeeded(), not(variables.SKIP_JOB), eq(variables['IMAGE'], 'mingw-check'))
   displayName: Verify the publish_toolstate script works
 
diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile
index 2041ba5..517b59c 100644
--- a/src/ci/docker/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/i686-gnu-nopt/Dockerfile
@@ -19,3 +19,6 @@
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
 ENV SCRIPT python2.7 ../x.py test
+
+# FIXME(#59637) takes too long on CI right now
+ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile
index 17441dd..03db3ba 100644
--- a/src/ci/docker/i686-gnu/Dockerfile
+++ b/src/ci/docker/i686-gnu/Dockerfile
@@ -25,3 +25,6 @@
   --exclude src/test/rustdoc-js \
   --exclude src/tools/error_index_generator \
   --exclude src/tools/linkchecker
+
+# FIXME(#59637) takes too long on CI right now
+ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
diff --git a/src/doc/book b/src/doc/book
index 7ddc464..871416b 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 7ddc46460f09a5cd9bd2a620565bdc20b3315ea9
+Subproject commit 871416b85c1a73717d65d6f4a9ea29e5aef3db0e
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index 432ca26..5ca585c 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit 432ca26686c11d396eed6a59499f93ce1bf2433c
+Subproject commit 5ca585c4a7552efb546e7681c3de0712f4ae4fdc
diff --git a/src/doc/nomicon b/src/doc/nomicon
index 38b9a76..4374786 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit 38b9a76bc8b59ac862663807fc51c9b757337fd6
+Subproject commit 4374786f0b4bf0606b35d5c30a9681f342e5707b
diff --git a/src/doc/reference b/src/doc/reference
index d191a0c..fa5dfb8 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit d191a0cdd3b92648e0f1e53b13140a14677cc65b
+Subproject commit fa5dfb832ef8a7568e17dabf612f486d641ff4ac
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 580839d..67cfbf3 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 580839d90aacd537f0293697096fa8355bc4e673
+Subproject commit 67cfbf31df880728dcf7cb35b15b028ec92caf31
diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide
index 6e25a3d..941968d 160000
--- a/src/doc/rustc-guide
+++ b/src/doc/rustc-guide
@@ -1 +1 @@
-Subproject commit 6e25a3d0d3573eb42b2e2339f1219e969d1b3dee
+Subproject commit 941968db2fd9c85788a4f971c8e425d46b4cb734
diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md
index 2ae726c..6f1bbe6 100644
--- a/src/doc/rustc/src/linker-plugin-lto.md
+++ b/src/doc/rustc/src/linker-plugin-lto.md
@@ -105,5 +105,6 @@
 | Rust 1.34 |     ✗     |     ✓     |
 | Rust 1.35 |     ✗     |     ✓     |
 | Rust 1.36 |     ✗     |     ✓     |
+| Rust 1.37 |     ✗     |     ✓     |
 
 Note that the compatibility policy for this feature might change in the future.
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 6e32468..49d05b5 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -311,19 +311,6 @@
 the crate root's docs. You can use this flag to differentiate between different versions of your
 library's documentation.
 
-### `--linker`: control the linker used for documentation tests
-
-Using this flag looks like this:
-
-```bash
-$ rustdoc --test src/lib.rs -Z unstable-options --linker foo
-$ rustdoc --test README.md -Z unstable-options --linker foo
-```
-
-When `rustdoc` runs your documentation tests, it needs to compile and link the tests as executables
-before running them. This flag can be used to change the linker used on these executables. It's
-equivalent to passing `-C linker=foo` to `rustc`.
-
 ### `--sort-modules-by-appearance`: control how items on module pages are sorted
 
 Using this flag looks like this:
@@ -484,3 +471,53 @@
 
 Public items that are not documented can be seen with the built-in `missing_docs` lint. Private
 items that are not documented can be seen with Clippy's `missing_docs_in_private_items` lint.
+
+### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs -Z unstable-options --enable-per-target-ignores
+```
+
+This flag allows you to tag doctests with compiltest style `ignore-foo` filters that prevent
+rustdoc from running that test if the target triple string contains foo. For example:
+
+```rust
+///```ignore-foo,ignore-bar
+///assert!(2 == 2);
+///```
+struct Foo;
+```
+
+This will not be run when the build target is `super-awesome-foo` or `less-bar-awesome`.
+If the flag is not enabled, then rustdoc will consume the filter, but do nothing with it, and
+the above example will be run for all targets.
+If you want to preserve backwards compatibility for older versions of rustdoc, you can use
+
+```rust
+///```ignore,ignore-foo
+///assert!(2 == 2);
+///```
+struct Foo;
+```
+
+In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will
+override `ignore`.
+
+### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it
+
+Using thses options looks like this:
+
+```bash
+$ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing
+```
+
+These options can be used to run the doctest under a program, and also pass arguments to
+that program. For example, if you want to run your doctests under valgrind you might run
+
+```bash
+$ rustdoc src/lib.rs -Z unstable-options --runtool valgrind
+```
+
+Another use case would be to run a test inside an emulator, or through a Virtual Machine.
diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
index 53e8393..68877b4 100644
--- a/src/doc/unstable-book/src/language-features/plugin.md
+++ b/src/doc/unstable-book/src/language-features/plugin.md
@@ -57,12 +57,12 @@
 extern crate rustc_driver;
 
 use syntax::parse::token::{self, Token};
-use syntax::tokenstream::TokenTree;
+use syntax::tokenstream::{TokenTree, TokenStream};
 use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
 use syntax_pos::Span;
 use rustc_driver::plugin::Registry;
 
-fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
+fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: TokenStream)
         -> Box<dyn MacResult + 'static> {
 
     static NUMERALS: &'static [(&'static str, usize)] = &[
@@ -78,7 +78,7 @@
         return DummyResult::any(sp);
     }
 
-    let text = match args[0] {
+    let text = match args.into_trees().next().unwrap() {
         TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(),
         _ => {
             cx.span_err(sp, "argument should be a single identifier");
diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode.py
index 537b419..7c2e914 100644
--- a/src/etc/lldb_batchmode.py
+++ b/src/etc/lldb_batchmode.py
@@ -45,7 +45,10 @@
 
 def breakpoint_callback(frame, bp_loc, dict):
     """This callback is registered with every breakpoint and makes sure that the
-    frame containing the breakpoint location is selected"""
+    frame containing the breakpoint location is selected """
+
+    # HACK(eddyb) print a newline to avoid continuing an unfinished line.
+    print("")
     print("Hit breakpoint " + str(bp_loc))
 
     # Select the frame and the thread containing it
diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs
index d3af910..0cb91ba 100644
--- a/src/liballoc/collections/btree/set.rs
+++ b/src/liballoc/collections/btree/set.rs
@@ -3,7 +3,7 @@
 
 use core::borrow::Borrow;
 use core::cmp::Ordering::{self, Less, Greater, Equal};
-use core::cmp::max;
+use core::cmp::{max, min};
 use core::fmt::{self, Debug};
 use core::iter::{Peekable, FromIterator, FusedIterator};
 use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeBounds};
@@ -187,8 +187,8 @@
 }
 enum IntersectionInner<'a, T: 'a> {
     Stitch {
-        small_iter: Iter<'a, T>, // for size_hint, should be the smaller of the sets
-        other_iter: Iter<'a, T>,
+        a: Iter<'a, T>,
+        b: Iter<'a, T>,
     },
     Search {
         small_iter: Iter<'a, T>,
@@ -201,12 +201,12 @@
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match &self.inner {
             IntersectionInner::Stitch {
-                small_iter,
-                other_iter,
+                a,
+                b,
             } => f
                 .debug_tuple("Intersection")
-                .field(&small_iter)
-                .field(&other_iter)
+                .field(&a)
+                .field(&b)
                 .finish(),
             IntersectionInner::Search {
                 small_iter,
@@ -397,8 +397,8 @@
             // Iterate both sets jointly, spotting matches along the way.
             Intersection {
                 inner: IntersectionInner::Stitch {
-                    small_iter: small.iter(),
-                    other_iter: other.iter(),
+                    a: small.iter(),
+                    b: other.iter(),
                 },
             }
         } else {
@@ -1221,11 +1221,11 @@
         Intersection {
             inner: match &self.inner {
                 IntersectionInner::Stitch {
-                    small_iter,
-                    other_iter,
+                    a,
+                    b,
                 } => IntersectionInner::Stitch {
-                    small_iter: small_iter.clone(),
-                    other_iter: other_iter.clone(),
+                    a: a.clone(),
+                    b: b.clone(),
                 },
                 IntersectionInner::Search {
                     small_iter,
@@ -1245,16 +1245,16 @@
     fn next(&mut self) -> Option<&'a T> {
         match &mut self.inner {
             IntersectionInner::Stitch {
-                small_iter,
-                other_iter,
+                a,
+                b,
             } => {
-                let mut small_next = small_iter.next()?;
-                let mut other_next = other_iter.next()?;
+                let mut a_next = a.next()?;
+                let mut b_next = b.next()?;
                 loop {
-                    match Ord::cmp(small_next, other_next) {
-                        Less => small_next = small_iter.next()?,
-                        Greater => other_next = other_iter.next()?,
-                        Equal => return Some(small_next),
+                    match Ord::cmp(a_next, b_next) {
+                        Less => a_next = a.next()?,
+                        Greater => b_next = b.next()?,
+                        Equal => return Some(a_next),
                     }
                 }
             }
@@ -1272,7 +1272,7 @@
 
     fn size_hint(&self) -> (usize, Option<usize>) {
         let min_len = match &self.inner {
-            IntersectionInner::Stitch { small_iter, .. } => small_iter.len(),
+            IntersectionInner::Stitch { a, b } => min(a.len(), b.len()),
             IntersectionInner::Search { small_iter, .. } => small_iter.len(),
         };
         (0, Some(min_len))
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index a14a3fe9..816a71f 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -276,7 +276,7 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new() -> Self {
+    pub const fn new() -> Self {
         LinkedList {
             head: None,
             tail: None,
diff --git a/src/liballoc/collections/linked_list/tests.rs b/src/liballoc/collections/linked_list/tests.rs
index 9a6c57d..ecb5948 100644
--- a/src/liballoc/collections/linked_list/tests.rs
+++ b/src/liballoc/collections/linked_list/tests.rs
@@ -102,8 +102,8 @@
         assert_eq!(m.pop_front(), Some(elt))
     }
     assert_eq!(n.len(), 0);
-    // let's make sure it's working properly, since we
-    // did some direct changes to private members
+    // Let's make sure it's working properly, since we
+    // did some direct changes to private members.
     n.push_back(3);
     assert_eq!(n.len(), 1);
     assert_eq!(n.pop_front(), Some(3));
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 4a48945..9e6ed92 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -117,7 +117,7 @@
 #![feature(allocator_internals)]
 #![feature(on_unimplemented)]
 #![feature(rustc_const_unstable)]
-#![feature(const_vec_new)]
+#![cfg_attr(bootstrap, feature(const_vec_new))]
 #![feature(slice_partition_dedup)]
 #![feature(maybe_uninit_extra, maybe_uninit_slice)]
 #![feature(alloc_layout_extra)]
@@ -171,3 +171,9 @@
 mod std {
     pub use core::ops; // RangeFull
 }
+
+#[doc(hidden)]
+#[unstable(feature = "liballoc_internals", issue = "0", reason = "implementation detail")]
+pub mod __export {
+    pub use core::format_args;
+}
diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs
index 0b5e186d..2f2cdc3 100644
--- a/src/liballoc/macros.rs
+++ b/src/liballoc/macros.rs
@@ -98,5 +98,5 @@
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! format {
-    ($($arg:tt)*) => ($crate::fmt::format(::core::format_args!($($arg)*)))
+    ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))
 }
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index bc8a38f..ee75fc2 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -19,26 +19,26 @@
 /// involved. This type is excellent for building your own data structures like Vec and VecDeque.
 /// In particular:
 ///
-/// * Produces Unique::empty() on zero-sized types
-/// * Produces Unique::empty() on zero-length allocations
-/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics)
-/// * Guards against 32-bit systems allocating more than isize::MAX bytes
-/// * Guards against overflowing your length
-/// * Aborts on OOM or calls handle_alloc_error as applicable
-/// * Avoids freeing Unique::empty()
-/// * Contains a ptr::Unique and thus endows the user with all related benefits
+/// * Produces `Unique::empty()` on zero-sized types.
+/// * Produces `Unique::empty()` on zero-length allocations.
+/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics).
+/// * Guards against 32-bit systems allocating more than isize::MAX bytes.
+/// * Guards against overflowing your length.
+/// * Aborts on OOM or calls `handle_alloc_error` as applicable.
+/// * Avoids freeing `Unique::empty()`.
+/// * Contains a `ptr::Unique` and thus endows the user with all related benefits.
 ///
 /// This type does not in anyway inspect the memory that it manages. When dropped it *will*
-/// free its memory, but it *won't* try to Drop its contents. It is up to the user of RawVec
-/// to handle the actual things *stored* inside of a RawVec.
+/// free its memory, but it *won't* try to drop its contents. It is up to the user of `RawVec`
+/// to handle the actual things *stored* inside of a `RawVec`.
 ///
-/// Note that a RawVec always forces its capacity to be usize::MAX for zero-sized types.
-/// This enables you to use capacity growing logic catch the overflows in your length
+/// Note that a `RawVec` always forces its capacity to be `usize::MAX` for zero-sized types.
+/// This enables you to use capacity-growing logic catch the overflows in your length
 /// that might occur with zero-sized types.
 ///
-/// However this means that you need to be careful when round-tripping this type
-/// with a `Box<[T]>`: `capacity()` won't yield the len. However `with_capacity`,
-/// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity
+/// The above means that you need to be careful when round-tripping this type with a
+/// `Box<[T]>`, since `capacity()` won't yield the length. However, `with_capacity`,
+/// `shrink_to_fit`, and `from_box` will actually set `RawVec`'s private capacity
 /// field. This allows zero-sized types to not be special-cased by consumers of
 /// this type.
 #[allow(missing_debug_implementations)]
@@ -49,14 +49,14 @@
 }
 
 impl<T, A: Alloc> RawVec<T, A> {
-    /// Like `new` but parameterized over the choice of allocator for
-    /// the returned RawVec.
+    /// Like `new`, but parameterized over the choice of allocator for
+    /// the returned `RawVec`.
     pub const fn new_in(a: A) -> Self {
-        // !0 is usize::MAX. This branch should be stripped at compile time.
-        // FIXME(mark-i-m): use this line when `if`s are allowed in `const`
+        // `!0` is `usize::MAX`. This branch should be stripped at compile time.
+        // FIXME(mark-i-m): use this line when `if`s are allowed in `const`:
         //let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
 
-        // Unique::empty() doubles as "unallocated" and "zero-sized allocation"
+        // `Unique::empty()` doubles as "unallocated" and "zero-sized allocation".
         RawVec {
             ptr: Unique::empty(),
             // FIXME(mark-i-m): use `cap` when ifs are allowed in const
@@ -65,15 +65,15 @@
         }
     }
 
-    /// Like `with_capacity` but parameterized over the choice of
-    /// allocator for the returned RawVec.
+    /// Like `with_capacity`, but parameterized over the choice of
+    /// allocator for the returned `RawVec`.
     #[inline]
     pub fn with_capacity_in(capacity: usize, a: A) -> Self {
         RawVec::allocate_in(capacity, false, a)
     }
 
-    /// Like `with_capacity_zeroed` but parameterized over the choice
-    /// of allocator for the returned RawVec.
+    /// Like `with_capacity_zeroed`, but parameterized over the choice
+    /// of allocator for the returned `RawVec`.
     #[inline]
     pub fn with_capacity_zeroed_in(capacity: usize, a: A) -> Self {
         RawVec::allocate_in(capacity, true, a)
@@ -86,7 +86,7 @@
             let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
             alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
 
-            // handles ZSTs and `capacity = 0` alike
+            // Handles ZSTs and `capacity == 0` alike.
             let ptr = if alloc_size == 0 {
                 NonNull::<T>::dangling()
             } else {
@@ -113,20 +113,45 @@
 }
 
 impl<T> RawVec<T, Global> {
-    /// Creates the biggest possible RawVec (on the system heap)
-    /// without allocating. If T has positive size, then this makes a
-    /// RawVec with capacity 0. If T has 0 size, then it makes a
-    /// RawVec with capacity `usize::MAX`. Useful for implementing
+    /// HACK(Centril): This exists because `#[unstable]` `const fn`s needn't conform
+    /// to `min_const_fn` and so they cannot be called in `min_const_fn`s either.
+    ///
+    /// If you change `RawVec<T>::new` or dependencies, please take care to not
+    /// introduce anything that would truly violate `min_const_fn`.
+    ///
+    /// NOTE: We could avoid this hack and check conformance with some
+    /// `#[rustc_force_min_const_fn]` attribute which requires conformance
+    /// with `min_const_fn` but does not necessarily allow calling it in
+    /// `stable(...) const fn` / user code not enabling `foo` when
+    /// `#[rustc_const_unstable(feature = "foo", ..)]` is present.
+    pub const NEW: Self = Self::new();
+
+    /// Creates the biggest possible `RawVec` (on the system heap)
+    /// without allocating. If `T` has positive size, then this makes a
+    /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a
+    /// `RawVec` with capacity `usize::MAX`. Useful for implementing
     /// delayed allocation.
     pub const fn new() -> Self {
-        Self::new_in(Global)
+        // FIXME(Centril): Reintegrate this with `fn new_in` when we can.
+
+        // `!0` is `usize::MAX`. This branch should be stripped at compile time.
+        // FIXME(mark-i-m): use this line when `if`s are allowed in `const`:
+        //let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
+
+        // `Unique::empty()` doubles as "unallocated" and "zero-sized allocation".
+        RawVec {
+            ptr: Unique::empty(),
+            // FIXME(mark-i-m): use `cap` when ifs are allowed in const
+            cap: [0, !0][(mem::size_of::<T>() == 0) as usize],
+            a: Global,
+        }
     }
 
-    /// Creates a RawVec (on the system heap) with exactly the
+    /// Creates a `RawVec` (on the system heap) with exactly the
     /// capacity and alignment requirements for a `[T; capacity]`. This is
-    /// equivalent to calling RawVec::new when `capacity` is 0 or T is
+    /// equivalent to calling `RawVec::new` when `capacity` is `0` or `T` is
     /// zero-sized. Note that if `T` is zero-sized this means you will
-    /// *not* get a RawVec with the requested capacity!
+    /// *not* get a `RawVec` with the requested capacity.
     ///
     /// # Panics
     ///
@@ -136,13 +161,13 @@
     ///
     /// # Aborts
     ///
-    /// Aborts on OOM
+    /// Aborts on OOM.
     #[inline]
     pub fn with_capacity(capacity: usize) -> Self {
         RawVec::allocate_in(capacity, false, Global)
     }
 
-    /// Like `with_capacity` but guarantees the buffer is zeroed.
+    /// Like `with_capacity`, but guarantees the buffer is zeroed.
     #[inline]
     pub fn with_capacity_zeroed(capacity: usize) -> Self {
         RawVec::allocate_in(capacity, true, Global)
@@ -150,13 +175,13 @@
 }
 
 impl<T, A: Alloc> RawVec<T, A> {
-    /// Reconstitutes a RawVec from a pointer, capacity, and allocator.
+    /// Reconstitutes a `RawVec` from a pointer, capacity, and allocator.
     ///
     /// # Undefined Behavior
     ///
-    /// The ptr must be allocated (via the given allocator `a`), and with the given capacity. The
-    /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems).
-    /// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed.
+    /// The `ptr` must be allocated (via the given allocator `a`), and with the given `capacity`.
+    /// The `capacity` cannot exceed `isize::MAX` (only a concern on 32-bit systems).
+    /// If the `ptr` and `capacity` come from a `RawVec` created via `a`, then this is guaranteed.
     pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, a: A) -> Self {
         RawVec {
             ptr: Unique::new_unchecked(ptr),
@@ -167,13 +192,13 @@
 }
 
 impl<T> RawVec<T, Global> {
-    /// Reconstitutes a RawVec from a pointer, capacity.
+    /// Reconstitutes a `RawVec` from a pointer and capacity.
     ///
     /// # Undefined Behavior
     ///
-    /// The ptr must be allocated (on the system heap), and with the given capacity. The
-    /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems).
-    /// If the ptr and capacity come from a RawVec, then this is guaranteed.
+    /// The `ptr` must be allocated (on the system heap), and with the given `capacity`.
+    /// The `capacity` cannot exceed `isize::MAX` (only a concern on 32-bit systems).
+    /// If the `ptr` and `capacity` come from a `RawVec`, then this is guaranteed.
     pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self {
         RawVec {
             ptr: Unique::new_unchecked(ptr),
@@ -194,7 +219,7 @@
 
 impl<T, A: Alloc> RawVec<T, A> {
     /// Gets a raw pointer to the start of the allocation. Note that this is
-    /// Unique::empty() if `capacity = 0` or T is zero-sized. In the former case, you must
+    /// `Unique::empty()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
     /// be careful.
     pub fn ptr(&self) -> *mut T {
         self.ptr.as_ptr()
@@ -212,12 +237,12 @@
         }
     }
 
-    /// Returns a shared reference to the allocator backing this RawVec.
+    /// Returns a shared reference to the allocator backing this `RawVec`.
     pub fn alloc(&self) -> &A {
         &self.a
     }
 
-    /// Returns a mutable reference to the allocator backing this RawVec.
+    /// Returns a mutable reference to the allocator backing this `RawVec`.
     pub fn alloc_mut(&mut self) -> &mut A {
         &mut self.a
     }
@@ -247,7 +272,7 @@
     ///
     /// # Panics
     ///
-    /// * Panics if T is zero-sized on the assumption that you managed to exhaust
+    /// * Panics if `T` is zero-sized on the assumption that you managed to exhaust
     ///   all `usize::MAX` slots in your imaginary buffer.
     /// * Panics on 32-bit platforms if the requested capacity exceeds
     ///   `isize::MAX` bytes.
@@ -290,20 +315,20 @@
         unsafe {
             let elem_size = mem::size_of::<T>();
 
-            // since we set the capacity to usize::MAX when elem_size is
-            // 0, getting to here necessarily means the RawVec is overfull.
+            // Since we set the capacity to `usize::MAX` when `elem_size` is
+            // 0, getting to here necessarily means the `RawVec` is overfull.
             assert!(elem_size != 0, "capacity overflow");
 
             let (new_cap, uniq) = match self.current_layout() {
                 Some(cur) => {
                     // Since we guarantee that we never allocate more than
-                    // isize::MAX bytes, `elem_size * self.cap <= isize::MAX` as
+                    // `isize::MAX` bytes, `elem_size * self.cap <= isize::MAX` as
                     // a precondition, so this can't overflow. Additionally the
                     // alignment will never be too large as to "not be
                     // satisfiable", so `Layout::from_size_align` will always
                     // return `Some`.
                     //
-                    // tl;dr; we bypass runtime checks due to dynamic assertions
+                    // TL;DR, we bypass runtime checks due to dynamic assertions
                     // in this module, allowing us to use
                     // `from_size_align_unchecked`.
                     let new_cap = 2 * self.cap;
@@ -320,8 +345,8 @@
                     }
                 }
                 None => {
-                    // skip to 4 because tiny Vec's are dumb; but not if that
-                    // would cause overflow
+                    // Skip to 4 because tiny `Vec`'s are dumb; but not if that
+                    // would cause overflow.
                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
                     match self.a.alloc_array::<T>(new_cap) {
                         Ok(ptr) => (new_cap, ptr.into()),
@@ -342,7 +367,7 @@
     ///
     /// # Panics
     ///
-    /// * Panics if T is zero-sized on the assumption that you managed to exhaust
+    /// * Panics if `T` is zero-sized on the assumption that you managed to exhaust
     ///   all `usize::MAX` slots in your imaginary buffer.
     /// * Panics on 32-bit platforms if the requested capacity exceeds
     ///   `isize::MAX` bytes.
@@ -356,15 +381,15 @@
                 None => return false, // nothing to double
             };
 
-            // since we set the capacity to usize::MAX when elem_size is
-            // 0, getting to here necessarily means the RawVec is overfull.
+            // Since we set the capacity to `usize::MAX` when `elem_size` is
+            // 0, getting to here necessarily means the `RawVec` is overfull.
             assert!(elem_size != 0, "capacity overflow");
 
-            // Since we guarantee that we never allocate more than isize::MAX
+            // Since we guarantee that we never allocate more than `isize::MAX`
             // bytes, `elem_size * self.cap <= isize::MAX` as a precondition, so
             // this can't overflow.
             //
-            // Similarly like with `double` above we can go straight to
+            // Similarly to with `double` above, we can go straight to
             // `Layout::from_size_align_unchecked` as we know this won't
             // overflow and the alignment is sufficiently small.
             let new_cap = 2 * self.cap;
@@ -409,7 +434,7 @@
     ///
     /// # Aborts
     ///
-    /// Aborts on OOM
+    /// Aborts on OOM.
     pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) {
         match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Exact) {
             Err(CapacityOverflow) => capacity_overflow(),
@@ -424,7 +449,7 @@
     fn amortized_new_size(&self, used_capacity: usize, needed_extra_capacity: usize)
         -> Result<usize, TryReserveError> {
 
-        // Nothing we can really do about these checks :(
+        // Nothing we can really do about these checks, sadly.
         let required_cap = used_capacity.checked_add(needed_extra_capacity)
             .ok_or(CapacityOverflow)?;
         // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
@@ -459,7 +484,7 @@
     ///
     /// # Aborts
     ///
-    /// Aborts on OOM
+    /// Aborts on OOM.
     ///
     /// # Examples
     ///
@@ -538,7 +563,7 @@
 
             // Here, `cap < used_capacity + needed_extra_capacity <= new_cap`
             // (regardless of whether `self.cap - used_capacity` wrapped).
-            // Therefore we can safely call grow_in_place.
+            // Therefore, we can safely call `grow_in_place`.
 
             let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
             // FIXME: may crash and burn on over-reserve
@@ -576,14 +601,14 @@
             return;
         }
 
-        // This check is my waterloo; it's the only thing Vec wouldn't have to do.
+        // This check is my waterloo; it's the only thing `Vec` wouldn't have to do.
         assert!(self.cap >= amount, "Tried to shrink to a larger capacity");
 
         if amount == 0 {
             // We want to create a new zero-length vector within the
-            // same allocator.  We use ptr::write to avoid an
+            // same allocator. We use `ptr::write` to avoid an
             // erroneous attempt to drop the contents, and we use
-            // ptr::read to sidestep condition against destructuring
+            // `ptr::read` to sidestep condition against destructuring
             // types that implement Drop.
 
             unsafe {
@@ -600,7 +625,7 @@
                 //
                 // We also know that `self.cap` is greater than `amount`, and
                 // consequently we don't need runtime checks for creating either
-                // layout
+                // layout.
                 let old_size = elem_size * self.cap;
                 let new_size = elem_size * amount;
                 let align = mem::align_of::<T>();
@@ -653,7 +678,7 @@
                 return Ok(());
             }
 
-            // Nothing we can really do about these checks :(
+            // Nothing we can really do about these checks, sadly.
             let new_cap = match strategy {
                 Exact => used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?,
                 Amortized => self.amortized_new_size(used_capacity, needed_extra_capacity)?,
@@ -692,7 +717,7 @@
     /// Converts the entire buffer into `Box<[T]>`.
     ///
     /// Note that this will correctly reconstitute any `cap` changes
-    /// that may have been performed. (see description of type for details)
+    /// that may have been performed. (See description of type for details.)
     ///
     /// # Undefined Behavior
     ///
@@ -700,7 +725,7 @@
     /// the rules around uninitialized boxed values are not finalized yet,
     /// but until they are, it is advisable to avoid them.
     pub unsafe fn into_box(self) -> Box<[T]> {
-        // NOTE: not calling `capacity()` here, actually using the real `cap` field!
+        // NOTE: not calling `capacity()` here; actually using the real `cap` field!
         let slice = slice::from_raw_parts_mut(self.ptr(), self.cap);
         let output: Box<[T]> = Box::from_raw(slice);
         mem::forget(self);
@@ -709,7 +734,7 @@
 }
 
 impl<T, A: Alloc> RawVec<T, A> {
-    /// Frees the memory owned by the RawVec *without* trying to Drop its contents.
+    /// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
     pub unsafe fn dealloc_buffer(&mut self) {
         let elem_size = mem::size_of::<T>();
         if elem_size != 0 {
@@ -721,22 +746,20 @@
 }
 
 unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> {
-    /// Frees the memory owned by the RawVec *without* trying to Drop its contents.
+    /// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
     fn drop(&mut self) {
         unsafe { self.dealloc_buffer(); }
     }
 }
 
-
-
 // We need to guarantee the following:
-// * We don't ever allocate `> isize::MAX` byte-size objects
-// * We don't overflow `usize::MAX` and actually allocate too little
+// * We don't ever allocate `> isize::MAX` byte-size objects.
+// * We don't overflow `usize::MAX` and actually allocate too little.
 //
 // On 64-bit we just need to check for overflow since trying to allocate
 // `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add
 // an extra guard for this in case we're running on a platform which can use
-// all 4GB in user-space. e.g., PAE or x32
+// all 4GB in user-space, e.g., PAE or x32.
 
 #[inline]
 fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
@@ -751,5 +774,5 @@
 // ensure that the code generation related to these panics is minimal as there's
 // only one location which panics rather than a bunch throughout the module.
 fn capacity_overflow() -> ! {
-    panic!("capacity overflow")
+    panic!("capacity overflow");
 }
diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs
index c389898..d35b62f 100644
--- a/src/liballoc/raw_vec/tests.rs
+++ b/src/liballoc/raw_vec/tests.rs
@@ -5,12 +5,12 @@
     use crate::alloc::AllocErr;
 
     // Writing a test of integration between third-party
-    // allocators and RawVec is a little tricky because the RawVec
+    // allocators and `RawVec` is a little tricky because the `RawVec`
     // API does not expose fallible allocation methods, so we
     // cannot check what happens when allocator is exhausted
     // (beyond detecting a panic).
     //
-    // Instead, this just checks that the RawVec methods do at
+    // Instead, this just checks that the `RawVec` methods do at
     // least go through the Allocator API when it reserves
     // storage.
 
@@ -44,7 +44,7 @@
 fn reserve_does_not_overallocate() {
     {
         let mut v: RawVec<u32> = RawVec::new();
-        // First `reserve` allocates like `reserve_exact`
+        // First, `reserve` allocates like `reserve_exact`.
         v.reserve(0, 9);
         assert_eq!(9, v.capacity());
     }
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 2b222ca..f234ac5 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -567,7 +567,7 @@
     ///     let x = Rc::from_raw(x_ptr);
     ///     assert_eq!(&*x, "hello");
     ///
-    ///     // Further calls to `Rc::from_raw(x_ptr)` would be memory unsafe.
+    ///     // Further calls to `Rc::from_raw(x_ptr)` would be memory-unsafe.
     /// }
     ///
     /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling!
@@ -1832,8 +1832,9 @@
         }
     }
 
-    /// Returns `true` if the two `Weak`s point to the same value (not just values
-    /// that compare as equal).
+    /// Returns `true` if the two `Weak`s point to the same value (not just
+    /// values that compare as equal), or if both don't point to any value
+    /// (because they were created with `Weak::new()`).
     ///
     /// # Notes
     ///
@@ -1843,7 +1844,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(weak_ptr_eq)]
     /// use std::rc::Rc;
     ///
     /// let first_rc = Rc::new(5);
@@ -1861,7 +1861,6 @@
     /// Comparing `Weak::new`.
     ///
     /// ```
-    /// #![feature(weak_ptr_eq)]
     /// use std::rc::{Rc, Weak};
     ///
     /// let first = Weak::new();
@@ -1873,7 +1872,7 @@
     /// assert!(!first.ptr_eq(&third));
     /// ```
     #[inline]
-    #[unstable(feature = "weak_ptr_eq", issue = "55981")]
+    #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
         self.ptr.as_ptr() == other.ptr.as_ptr()
     }
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index b65f191..1166e7b 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -369,7 +369,7 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_string_new")]
+    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_string_new"))]
     pub const fn new() -> String {
         String { vec: Vec::new() }
     }
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 9ffc167..45f9816 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -547,7 +547,7 @@
     ///     let x = Arc::from_raw(x_ptr);
     ///     assert_eq!(&*x, "hello");
     ///
-    ///     // Further calls to `Arc::from_raw(x_ptr)` would be memory unsafe.
+    ///     // Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe.
     /// }
     ///
     /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling!
@@ -1550,19 +1550,18 @@
         }
     }
 
-    /// Returns `true` if the two `Weak`s point to the same value (not just values
-    /// that compare as equal).
+    /// Returns `true` if the two `Weak`s point to the same value (not just
+    /// values that compare as equal), or if both don't point to any value
+    /// (because they were created with `Weak::new()`).
     ///
     /// # Notes
     ///
     /// Since this compares pointers it means that `Weak::new()` will equal each
     /// other, even though they don't point to any value.
     ///
-    ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(weak_ptr_eq)]
     /// use std::sync::Arc;
     ///
     /// let first_rc = Arc::new(5);
@@ -1580,7 +1579,6 @@
     /// Comparing `Weak::new`.
     ///
     /// ```
-    /// #![feature(weak_ptr_eq)]
     /// use std::sync::{Arc, Weak};
     ///
     /// let first = Weak::new();
@@ -1592,7 +1590,7 @@
     /// assert!(!first.ptr_eq(&third));
     /// ```
     #[inline]
-    #[unstable(feature = "weak_ptr_eq", issue = "55981")]
+    #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
         self.ptr.as_ptr() == other.ptr.as_ptr()
     }
diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs
index 62ccb53..35db18c 100644
--- a/src/liballoc/tests/btree/set.rs
+++ b/src/liballoc/tests/btree/set.rs
@@ -91,6 +91,17 @@
 }
 
 #[test]
+fn test_intersection_size_hint() {
+    let x: BTreeSet<i32> = [3, 4].iter().copied().collect();
+    let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
+    let mut iter = x.intersection(&y);
+    assert_eq!(iter.size_hint(), (0, Some(2)));
+    assert_eq!(iter.next(), Some(&3));
+    assert_eq!(iter.size_hint(), (0, Some(0)));
+    assert_eq!(iter.next(), None);
+}
+
+#[test]
 fn test_difference() {
     fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) {
         check(a, b, expected, |x, y, f| x.difference(y).all(f))
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index d5dc2d4..405969a 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -314,10 +314,10 @@
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_vec_new")]
+    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_vec_new"))]
     pub const fn new() -> Vec<T> {
         Vec {
-            buf: RawVec::new(),
+            buf: RawVec::NEW,
             len: 0,
         }
     }
@@ -685,21 +685,25 @@
     /// [`drain`]: #method.drain
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, len: usize) {
-        let current_len = self.len;
-        unsafe {
-            let mut ptr = self.as_mut_ptr().add(self.len);
-            // Set the final length at the end, keeping in mind that
-            // dropping an element might panic. Works around a missed
-            // optimization, as seen in the following issue:
-            // https://github.com/rust-lang/rust/issues/51802
-            let mut local_len = SetLenOnDrop::new(&mut self.len);
+        if mem::needs_drop::<T>() {
+            let current_len = self.len;
+            unsafe {
+                let mut ptr = self.as_mut_ptr().add(self.len);
+                // Set the final length at the end, keeping in mind that
+                // dropping an element might panic. Works around a missed
+                // optimization, as seen in the following issue:
+                // https://github.com/rust-lang/rust/issues/51802
+                let mut local_len = SetLenOnDrop::new(&mut self.len);
 
-            // drop any extra elements
-            for _ in len..current_len {
-                local_len.decrement_len(1);
-                ptr = ptr.offset(-1);
-                ptr::drop_in_place(ptr);
+                // drop any extra elements
+                for _ in len..current_len {
+                    local_len.decrement_len(1);
+                    ptr = ptr.offset(-1);
+                    ptr::drop_in_place(ptr);
+                }
             }
+        } else if len <= self.len {
+            self.len = len;
         }
     }
 
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index e8a0a88..0afbf4f 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -153,13 +153,13 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is<T: Any>(&self) -> bool {
-        // Get TypeId of the type this function is instantiated with
+        // Get `TypeId` of the type this function is instantiated with.
         let t = TypeId::of::<T>();
 
-        // Get TypeId of the type in the trait object
+        // Get `TypeId` of the type in the trait object.
         let concrete = self.type_id();
 
-        // Compare both TypeIds on equality
+        // Compare both `TypeId`s on equality.
         t == concrete
     }
 
diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs
new file mode 100644
index 0000000..32ec269
--- /dev/null
+++ b/src/libcore/bool.rs
@@ -0,0 +1,45 @@
+//! impl bool {}
+
+#[cfg(not(boostrap_stdarch_ignore_this))]
+#[lang = "bool"]
+impl bool {
+    /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(bool_to_option)]
+    ///
+    /// assert_eq!(false.then(0), None);
+    /// assert_eq!(true.then(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
+        }
+    }
+
+    /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(bool_to_option)]
+    ///
+    /// assert_eq!(false.then_with(|| 0), None);
+    /// assert_eq!(true.then_with(|| 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
+        }
+    }
+}
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index e91bf53..a69eb0f 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -547,29 +547,6 @@
         }
     }
 
-    /// Returns `true` if this `char` satisfies the `XID_Start` Unicode property, and false
-    /// otherwise.
-    ///
-    /// `XID_Start` is a Unicode Derived Property specified in
-    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
-    /// mostly similar to `ID_Start` but modified for closure under `NFKx`.
-    #[unstable(feature = "unicode_internals", issue = "0")]
-    pub fn is_xid_start(self) -> bool {
-        derived_property::XID_Start(self)
-    }
-
-    /// Returns `true` if this `char` satisfies the `XID_Continue` Unicode property, and false
-    /// otherwise.
-    ///
-    /// `XID_Continue` is a Unicode Derived Property specified in
-    /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
-    /// mostly similar to `ID_Continue` but modified for closure under NFKx.
-    #[unstable(feature = "unicode_internals", issue = "0")]
-    #[inline]
-    pub fn is_xid_continue(self) -> bool {
-        derived_property::XID_Continue(self)
-    }
-
     /// Returns `true` if this `char` is lowercase.
     ///
     /// 'Lowercase' is defined according to the terms of the Unicode Derived Core
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 607427a..7ec2295 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -9,14 +9,22 @@
 //! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and
 //!   partial orderings between values, respectively. Implementing them overloads
 //!   the `<`, `<=`, `>`, and `>=` operators.
-//! * [`Ordering`][cmp::Ordering] is an enum returned by the
-//!   main functions of [`Ord`] and [`PartialOrd`], and describes an ordering.
-//! * [`Reverse`][cmp::Reverse] is a struct that allows you to easily reverse
-//!   an ordering.
-//! * [`max`][cmp::max] and [`min`][cmp::min] are functions that build off of
-//!   [`Ord`] and allow you to find the maximum or minimum of two values.
+//! * [`Ordering`] is an enum returned by the main functions of [`Ord`] and
+//!   [`PartialOrd`], and describes an ordering.
+//! * [`Reverse`] is a struct that allows you to easily reverse an ordering.
+//! * [`max`] and [`min`] are functions that build off of [`Ord`] and allow you
+//!   to find the maximum or minimum of two values.
 //!
 //! For more details, see the respective documentation of each item in the list.
+//!
+//! [`Eq`]: trait.Eq.html
+//! [`PartialEq`]: trait.PartialEq.html
+//! [`Ord`]: trait.Ord.html
+//! [`PartialOrd`]: trait.PartialOrd.html
+//! [`Ordering`]: enum.Ordering.html
+//! [`Reverse`]: struct.Reverse.html
+//! [`max`]: fn.max.html
+//! [`min`]: fn.min.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index 641621f..06f2b7b 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -42,11 +42,11 @@
 
 use crate::fmt;
 
-/// An identity function.
+/// The identity function.
 ///
 /// Two things are important to note about this function:
 ///
-/// - It is not always equivalent to a closure like `|x| x` since the
+/// - It is not always equivalent to a closure like `|x| x`, since the
 ///   closure may coerce `x` into a different type.
 ///
 /// - It moves the input `x` passed to the function.
@@ -56,31 +56,32 @@
 ///
 /// # Examples
 ///
-/// Using `identity` to do nothing among other interesting functions:
+/// Using `identity` to do nothing in a sequence of other, interesting,
+/// functions:
 ///
 /// ```rust
 /// use std::convert::identity;
 ///
 /// fn manipulation(x: u32) -> u32 {
-///     // Let's assume that this function does something interesting.
+///     // Let's pretend that adding one is an interesting function.
 ///     x + 1
 /// }
 ///
 /// let _arr = &[identity, manipulation];
 /// ```
 ///
-/// Using `identity` to get a function that changes nothing in a conditional:
+/// Using `identity` as a "do nothing" base case in a conditional:
 ///
 /// ```rust
 /// use std::convert::identity;
 ///
 /// # let condition = true;
-///
+/// #
 /// # fn manipulation(x: u32) -> u32 { x + 1 }
-///
+/// #
 /// let do_stuff = if condition { manipulation } else { identity };
 ///
-/// // do more interesting stuff..
+/// // Do more interesting stuff...
 ///
 /// let _results = do_stuff(42);
 /// ```
@@ -104,22 +105,17 @@
 /// If you need to do a costly conversion it is better to implement [`From`] with type
 /// `&T` or write a custom function.
 ///
-/// `AsRef` has the same signature as [`Borrow`], but `Borrow` is different in few aspects:
+/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in few aspects:
 ///
-/// - Unlike `AsRef`, `Borrow` has a blanket impl for any `T`, and can be used to accept either
+/// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either
 ///   a reference or a value.
-/// - `Borrow` also requires that `Hash`, `Eq` and `Ord` for borrowed value are
+/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for borrowed value are
 ///   equivalent to those of the owned value. For this reason, if you want to
-///   borrow only a single field of a struct you can implement `AsRef`, but not `Borrow`.
-///
-/// [`Borrow`]: ../../std/borrow/trait.Borrow.html
+///   borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`].
 ///
 /// **Note: This trait must not fail**. If the conversion can fail, use a
 /// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
 ///
-/// [`Option<T>`]: ../../std/option/enum.Option.html
-/// [`Result<T, E>`]: ../../std/result/enum.Result.html
-///
 /// # Generic Implementations
 ///
 /// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
@@ -132,9 +128,16 @@
 /// converted to the specified type `T`.
 ///
 /// For example: By creating a generic function that takes an `AsRef<str>` we express that we
-/// want to accept all references that can be converted to `&str` as an argument.
-/// Since both [`String`] and `&str` implement `AsRef<str>` we can accept both as input argument.
+/// want to accept all references that can be converted to [`&str`] as an argument.
+/// Since both [`String`] and [`&str`] implement `AsRef<str>` we can accept both as input argument.
 ///
+/// [`Option<T>`]: ../../std/option/enum.Option.html
+/// [`Result<T, E>`]: ../../std/result/enum.Result.html
+/// [`Borrow`]: ../../std/borrow/trait.Borrow.html
+/// [`Hash`]: ../../std/hash/trait.Hash.html
+/// [`Eq`]: ../../std/cmp/trait.Eq.html
+/// [`Ord`]: ../../std/cmp/trait.Ord.html
+/// [`&str`]: ../../std/primitive.str.html
 /// [`String`]: ../../std/string/struct.String.html
 ///
 /// ```
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index 6439fa0..ee4be6c 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -49,28 +49,16 @@
     intrinsics::unreachable()
 }
 
-/// Signals the processor that it is entering a busy-wait spin-loop.
+/// Emits a machine instruction hinting to the processor that it is running in busy-wait
+/// spin-loop ("spin lock").
 ///
-/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
-/// power or switching hyper-threads.
-///
-/// This function is different than [`std::thread::yield_now`] which directly yields to the
-/// system's scheduler, whereas `spin_loop` only signals the processor that it is entering a
-/// busy-wait spin-loop without yielding control to the system's scheduler.
-///
-/// Using a busy-wait spin-loop with `spin_loop` is ideally used in situations where a
-/// contended lock is held by another thread executed on a different CPU and where the waiting
-/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's
-/// scheduler, no overhead for switching threads occurs. However, if the thread holding the
-/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice
-/// before switching to the thread that holds the lock. If the contending lock is held by a thread
-/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to
-/// use [`std::thread::yield_now`].
+/// For a discussion of different locking strategies and their trade-offs, see
+/// [`core::sync::atomic::spin_loop_hint`].
 ///
 /// **Note**: On platforms that do not support receiving spin-loop hints this function does not
 /// do anything at all.
 ///
-/// [`std::thread::yield_now`]: ../../std/thread/fn.yield_now.html
+/// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html
 #[inline]
 #[unstable(feature = "renamed_spin_loop", issue = "55002")]
 pub fn spin_loop() {
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index d145f22..ecff40a 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -845,21 +845,26 @@
     ///
     /// ```
     /// let store = [0, 1, 2, 3];
-    /// let mut v_orig = store.iter().collect::<Vec<&i32>>();
+    /// let v_orig = store.iter().collect::<Vec<&i32>>();
+    ///
+    /// // clone the vector as we will reuse them later
+    /// let v_clone = v_orig.clone();
     ///
     /// // Using transmute: this is Undefined Behavior, and a bad idea.
     /// // However, it is no-copy.
     /// let v_transmuted = unsafe {
-    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
-    ///         v_orig.clone())
+    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
     /// };
     ///
+    /// let v_clone = v_orig.clone();
+    ///
     /// // This is the suggested, safe way.
     /// // It does copy the entire vector, though, into a new array.
-    /// let v_collected = v_orig.clone()
-    ///                         .into_iter()
-    ///                         .map(|r| Some(r))
-    ///                         .collect::<Vec<Option<&i32>>>();
+    /// let v_collected = v_clone.into_iter()
+    ///                          .map(Some)
+    ///                          .collect::<Vec<Option<&i32>>>();
+    ///
+    /// let v_clone = v_orig.clone();
     ///
     /// // The no-copy, unsafe way, still using transmute, but not UB.
     /// // This is equivalent to the original, but safer, and reuses the
@@ -869,11 +874,12 @@
     /// // the original inner type (`&i32`) to the converted inner type
     /// // (`Option<&i32>`), so read the nomicon pages linked above.
     /// let v_from_raw = unsafe {
-    ///     Vec::from_raw_parts(v_orig.as_mut_ptr() as *mut Option<&i32>,
-    ///                         v_orig.len(),
-    ///                         v_orig.capacity())
+    ///     // Ensure the original vector is not dropped.
+    ///     let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
+    ///     Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,
+    ///                         v_clone.len(),
+    ///                         v_clone.capacity())
     /// };
-    /// std::mem::forget(v_orig);
     /// ```
     ///
     /// Implementing `split_at_mut`:
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index f507818..3b8edc2 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -5,7 +5,7 @@
 use crate::intrinsics;
 
 use super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};
-use super::LoopState;
+use super::{LoopState, from_fn};
 
 mod chain;
 mod flatten;
@@ -66,13 +66,6 @@
     {
         self.iter.rfind(predicate)
     }
-
-    #[inline]
-    fn rposition<P>(&mut self, predicate: P) -> Option<usize> where
-        P: FnMut(Self::Item) -> bool
-    {
-        self.iter.position(predicate)
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -541,6 +534,26 @@
             self.iter.nth(nth - 1);
         }
     }
+
+    fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
+    where
+        F: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        #[inline]
+        fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
+            move || iter.nth(step)
+        }
+
+        if self.first_take {
+            self.first_take = false;
+            match self.iter.next() {
+                None => return Try::from_ok(acc),
+                Some(x) => acc = f(acc, x)?,
+            }
+        }
+        from_fn(nth(&mut self.iter, self.step)).try_fold(acc, f)
+    }
 }
 
 impl<I> StepBy<I> where I: ExactSizeIterator {
@@ -574,6 +587,28 @@
             .saturating_add(self.next_back_index());
         self.iter.nth_back(n)
     }
+
+    fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
+    where
+        F: FnMut(Acc, Self::Item) -> R,
+        R: Try<Ok = Acc>,
+    {
+        #[inline]
+        fn nth_back<I: DoubleEndedIterator>(
+            iter: &mut I,
+            step: usize,
+        ) -> impl FnMut() -> Option<I::Item> + '_ {
+            move || iter.nth_back(step)
+        }
+
+        match self.next_back() {
+            None => Try::from_ok(init),
+            Some(x) => {
+                let acc = f(init, x)?;
+                from_fn(nth_back(&mut self.iter, self.step)).try_fold(acc, f)
+            }
+        }
+    }
 }
 
 // StepBy can only make the iterator shorter, so the len will still fit.
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index d644787..c09df3f 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -2546,12 +2546,52 @@
 
     /// Lexicographically compares the elements of this `Iterator` with those
     /// of another.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::cmp::Ordering;
+    ///
+    /// assert_eq!([1].iter().cmp([1].iter()), Ordering::Equal);
+    /// assert_eq!([1].iter().cmp([1, 2].iter()), Ordering::Less);
+    /// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater);
+    /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    fn cmp<I>(mut self, other: I) -> Ordering where
+    fn cmp<I>(self, other: I) -> Ordering
+    where
         I: IntoIterator<Item = Self::Item>,
         Self::Item: Ord,
         Self: Sized,
     {
+        self.cmp_by(other, |x, y| x.cmp(&y))
+    }
+
+    /// Lexicographically compares the elements of this `Iterator` with those
+    /// of another with respect to the specified comparison function.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iter_order_by)]
+    ///
+    /// use std::cmp::Ordering;
+    ///
+    /// let xs = [1, 2, 3, 4];
+    /// let ys = [1, 4, 9, 16];
+    ///
+    /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| x.cmp(&y)), Ordering::Less);
+    /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (x * x).cmp(&y)), Ordering::Equal);
+    /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater);
+    /// ```
+    #[unstable(feature = "iter_order_by", issue = "0")]
+    fn cmp_by<I, F>(mut self, other: I, mut cmp: F) -> Ordering
+    where
+        Self: Sized,
+        I: IntoIterator,
+        F: FnMut(Self::Item, I::Item) -> Ordering,
+    {
         let mut other = other.into_iter();
 
         loop {
@@ -2569,7 +2609,7 @@
                 Some(val) => val,
             };
 
-            match x.cmp(&y) {
+            match cmp(x, y) {
                 Ordering::Equal => (),
                 non_eq => return non_eq,
             }
@@ -2578,12 +2618,63 @@
 
     /// Lexicographically compares the elements of this `Iterator` with those
     /// of another.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::cmp::Ordering;
+    ///
+    /// assert_eq!([1.].iter().partial_cmp([1.].iter()), Some(Ordering::Equal));
+    /// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less));
+    /// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater));
+    ///
+    /// assert_eq!([std::f64::NAN].iter().partial_cmp([1.].iter()), None);
+    /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    fn partial_cmp<I>(mut self, other: I) -> Option<Ordering> where
+    fn partial_cmp<I>(self, other: I) -> Option<Ordering>
+    where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
         Self: Sized,
     {
+        self.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
+    }
+
+    /// Lexicographically compares the elements of this `Iterator` with those
+    /// of another with respect to the specified comparison function.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iter_order_by)]
+    ///
+    /// use std::cmp::Ordering;
+    ///
+    /// let xs = [1.0, 2.0, 3.0, 4.0];
+    /// let ys = [1.0, 4.0, 9.0, 16.0];
+    ///
+    /// assert_eq!(
+    ///     xs.iter().partial_cmp_by(&ys, |&x, &y| x.partial_cmp(&y)),
+    ///     Some(Ordering::Less)
+    /// );
+    /// assert_eq!(
+    ///     xs.iter().partial_cmp_by(&ys, |&x, &y| (x * x).partial_cmp(&y)),
+    ///     Some(Ordering::Equal)
+    /// );
+    /// assert_eq!(
+    ///     xs.iter().partial_cmp_by(&ys, |&x, &y| (2.0 * x).partial_cmp(&y)),
+    ///     Some(Ordering::Greater)
+    /// );
+    /// ```
+    #[unstable(feature = "iter_order_by", issue = "0")]
+    fn partial_cmp_by<I, F>(mut self, other: I, mut partial_cmp: F) -> Option<Ordering>
+    where
+        Self: Sized,
+        I: IntoIterator,
+        F: FnMut(Self::Item, I::Item) -> Option<Ordering>,
+    {
         let mut other = other.into_iter();
 
         loop {
@@ -2601,7 +2692,7 @@
                 Some(val) => val,
             };
 
-            match x.partial_cmp(&y) {
+            match partial_cmp(x, y) {
                 Some(Ordering::Equal) => (),
                 non_eq => return non_eq,
             }
@@ -2610,12 +2701,45 @@
 
     /// Determines if the elements of this `Iterator` are equal to those of
     /// another.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!([1].iter().eq([1].iter()), true);
+    /// assert_eq!([1].iter().eq([1, 2].iter()), false);
+    /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
-    fn eq<I>(mut self, other: I) -> bool where
+    fn eq<I>(self, other: I) -> bool
+    where
         I: IntoIterator,
         Self::Item: PartialEq<I::Item>,
         Self: Sized,
     {
+        self.eq_by(other, |x, y| x == y)
+    }
+
+    /// Determines if the elements of this `Iterator` are equal to those of
+    /// another with respect to the specified equality function.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iter_order_by)]
+    ///
+    /// let xs = [1, 2, 3, 4];
+    /// let ys = [1, 4, 9, 16];
+    ///
+    /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y));
+    /// ```
+    #[unstable(feature = "iter_order_by", issue = "0")]
+    fn eq_by<I, F>(mut self, other: I, mut eq: F) -> bool
+    where
+        Self: Sized,
+        I: IntoIterator,
+        F: FnMut(Self::Item, I::Item) -> bool,
+    {
         let mut other = other.into_iter();
 
         loop {
@@ -2629,12 +2753,21 @@
                 Some(val) => val,
             };
 
-            if x != y { return false }
+            if !eq(x, y) {
+                return false;
+            }
         }
     }
 
     /// Determines if the elements of this `Iterator` are unequal to those of
     /// another.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!([1].iter().ne([1].iter()), false);
+    /// assert_eq!([1].iter().ne([1, 2].iter()), true);
+    /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
     fn ne<I>(self, other: I) -> bool where
         I: IntoIterator,
@@ -2646,6 +2779,14 @@
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// less than those of another.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!([1].iter().lt([1].iter()), false);
+    /// assert_eq!([1].iter().lt([1, 2].iter()), true);
+    /// assert_eq!([1, 2].iter().lt([1].iter()), false);
+    /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
     fn lt<I>(self, other: I) -> bool where
         I: IntoIterator,
@@ -2657,6 +2798,14 @@
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// less or equal to those of another.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!([1].iter().le([1].iter()), true);
+    /// assert_eq!([1].iter().le([1, 2].iter()), true);
+    /// assert_eq!([1, 2].iter().le([1].iter()), false);
+    /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
     fn le<I>(self, other: I) -> bool where
         I: IntoIterator,
@@ -2671,6 +2820,14 @@
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// greater than those of another.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!([1].iter().gt([1].iter()), false);
+    /// assert_eq!([1].iter().gt([1, 2].iter()), false);
+    /// assert_eq!([1, 2].iter().gt([1].iter()), true);
+    /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
     fn gt<I>(self, other: I) -> bool where
         I: IntoIterator,
@@ -2682,6 +2839,14 @@
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// greater than or equal to those of another.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!([1].iter().ge([1].iter()), true);
+    /// assert_eq!([1].iter().ge([1, 2].iter()), false);
+    /// assert_eq!([1, 2].iter().ge([1].iter()), true);
+    /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
     fn ge<I>(self, other: I) -> bool where
         I: IntoIterator,
@@ -2730,6 +2895,18 @@
     /// function to determine the ordering of two elements. Apart from that, it's equivalent to
     /// [`is_sorted`]; see its documentation for more information.
     ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_sorted)]
+    ///
+    /// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
+    /// assert!(![1, 3, 2, 4].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
+    /// assert!([0].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
+    /// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| a.partial_cmp(b)));
+    /// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
+    /// ```
+    ///
     /// [`is_sorted`]: trait.Iterator.html#method.is_sorted
     #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
     fn is_sorted_by<F>(mut self, mut compare: F) -> bool
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index c168d5c..a2cc585 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -87,7 +87,7 @@
 #![feature(link_llvm_intrinsics)]
 #![feature(never_type)]
 #![feature(nll)]
-#![feature(bind_by_move_pattern_guards)]
+#![cfg_attr(boostrap_stdarch_ignore_this, feature(bind_by_move_pattern_guards))]
 #![feature(exhaustive_patterns)]
 #![feature(no_core)]
 #![feature(on_unimplemented)]
@@ -227,6 +227,7 @@
 pub mod alloc;
 
 // note: does not need to be public
+mod bool;
 mod tuple;
 mod unit;
 
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index ffaca02..384bc87 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -1236,8 +1236,10 @@
     pub macro test($item:item) { /* compiler built-in */ }
 
     /// Attribute macro applied to a function to turn it into a benchmark test.
-    #[unstable(feature = "test", issue = "50297",
-               reason = "`bench` is a part of custom test frameworks which are unstable")]
+    #[cfg_attr(not(boostrap_stdarch_ignore_this), unstable(soft, feature = "test", issue = "50297",
+               reason = "`bench` is a part of custom test frameworks which are unstable"))]
+    #[cfg_attr(boostrap_stdarch_ignore_this, unstable(feature = "test", issue = "50297",
+               reason = "`bench` is a part of custom test frameworks which are unstable"))]
     #[allow_internal_unstable(test, rustc_attrs)]
     #[rustc_builtin_macro]
     pub macro bench($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 89af252..347e7dc 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -602,10 +602,10 @@
 unsafe impl<T: ?Sized> Freeze for &T {}
 unsafe impl<T: ?Sized> Freeze for &mut T {}
 
-/// Types which can be safely moved after being pinned.
+/// Types that can be safely moved after being pinned.
 ///
 /// Since Rust itself has no notion of immovable types, and considers moves
-/// (e.g. through assignment or [`mem::replace`]) to always be safe,
+/// (e.g., through assignment or [`mem::replace`]) to always be safe,
 /// this trait cannot prevent types from moving by itself.
 ///
 /// Instead it is used to prevent moves through the type system,
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index b46e06f..0cf2ebb 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1401,12 +1401,8 @@
 ```"),
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
             #[inline]
-            pub fn wrapping_abs(self) -> Self {
-                if self.is_negative() {
-                    self.wrapping_neg()
-                } else {
-                    self
-                }
+            pub const fn wrapping_abs(self) -> Self {
+                (self ^ (self >> ($BITS - 1))).wrapping_sub(self >> ($BITS - 1))
             }
         }
 
@@ -1764,12 +1760,8 @@
 ```"),
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
             #[inline]
-            pub fn overflowing_abs(self) -> (Self, bool) {
-                if self.is_negative() {
-                    self.overflowing_neg()
-                } else {
-                    (self, false)
-                }
+            pub const fn overflowing_abs(self) -> (Self, bool) {
+                (self ^ (self >> ($BITS - 1))).overflowing_sub(self >> ($BITS - 1))
             }
         }
 
@@ -1973,15 +1965,11 @@
             #[stable(feature = "rust1", since = "1.0.0")]
             #[inline]
             #[rustc_inherit_overflow_checks]
-            pub fn abs(self) -> Self {
-                if self.is_negative() {
-                    // Note that the #[inline] above means that the overflow
-                    // semantics of this negation depend on the crate we're being
-                    // inlined into.
-                    -self
-                } else {
-                    self
-                }
+            pub const fn abs(self) -> Self {
+                // Note that the #[inline] above means that the overflow
+                // semantics of the subtraction depend on the crate we're being
+                // inlined into.
+                (self ^ (self >> ($BITS - 1))) - (self >> ($BITS - 1))
             }
         }
 
@@ -2104,11 +2092,14 @@
 
 ```
 let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();
-assert_eq!(bytes, if cfg!(target_endian = \"big\") {
+assert_eq!(
+    bytes,
+    if cfg!(target_endian = \"big\") {
         ", $be_bytes, "
     } else {
         ", $le_bytes, "
-    });
+    }
+);
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
@@ -2200,10 +2191,10 @@
 
 ```
 let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {
-        ", $be_bytes, "
-    } else {
-        ", $le_bytes, "
-    });
+    ", $be_bytes, "
+} else {
+    ", $le_bytes, "
+});
 assert_eq!(value, ", $swap_op, ");
 ```
 
@@ -3923,11 +3914,14 @@
 
 ```
 let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();
-assert_eq!(bytes, if cfg!(target_endian = \"big\") {
+assert_eq!(
+    bytes,
+    if cfg!(target_endian = \"big\") {
         ", $be_bytes, "
     } else {
         ", $le_bytes, "
-    });
+    }
+);
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
@@ -4019,10 +4013,10 @@
 
 ```
 let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {
-        ", $be_bytes, "
-    } else {
-        ", $le_bytes, "
-    });
+    ", $be_bytes, "
+} else {
+    ", $le_bytes, "
+});
 assert_eq!(value, ", $swap_op, ");
 ```
 
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
index fd129a3..59a10ae 100644
--- a/src/libcore/num/wrapping.rs
+++ b/src/libcore/num/wrapping.rs
@@ -18,6 +18,8 @@
                 }
             }
         }
+        forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f,
+                #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl ShlAssign<$f> for Wrapping<$t> {
@@ -41,6 +43,8 @@
                 }
             }
         }
+        forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f,
+                #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl ShrAssign<$f> for Wrapping<$t> {
@@ -64,6 +68,8 @@
                 Wrapping(self.0.wrapping_shl((other & self::shift_max::$t as $f) as u32))
             }
         }
+        forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f,
+                #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl ShlAssign<$f> for Wrapping<$t> {
@@ -83,6 +89,8 @@
                 Wrapping(self.0.wrapping_shr((other & self::shift_max::$t as $f) as u32))
             }
         }
+        forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f,
+                #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl ShrAssign<$f> for Wrapping<$t> {
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 259ed36..5569d99 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -295,7 +295,7 @@
     /// [`Pin`]: ../pin/struct.Pin.html
     #[inline]
     #[stable(feature = "pin", since = "1.33.0")]
-    pub fn as_pin_ref<'a>(self: Pin<&'a Option<T>>) -> Option<Pin<&'a T>> {
+    pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
         unsafe {
             Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x))
         }
@@ -306,7 +306,7 @@
     /// [`Pin`]: ../pin/struct.Pin.html
     #[inline]
     #[stable(feature = "pin", since = "1.33.0")]
-    pub fn as_pin_mut<'a>(self: Pin<&'a mut Option<T>>) -> Option<Pin<&'a mut T>> {
+    pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
         unsafe {
             Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x))
         }
@@ -1110,6 +1110,18 @@
     /// to the original one, additionally coercing the contents via [`Deref`].
     ///
     /// [`Deref`]: ../../std/ops/trait.Deref.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inner_deref)]
+    ///
+    /// let x: Option<String> = Some("hey".to_owned());
+    /// assert_eq!(x.as_deref(), Some("hey"));
+    ///
+    /// let x: Option<String> = None;
+    /// assert_eq!(x.as_deref(), None);
+    /// ```
     pub fn as_deref(&self) -> Option<&T::Target> {
         self.as_ref().map(|t| t.deref())
     }
@@ -1121,6 +1133,18 @@
     ///
     /// Leaves the original `Option` in-place, creating a new one containing a mutable reference to
     /// the inner type's `Deref::Target` type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inner_deref)]
+    ///
+    /// let mut x: Option<String> = Some("hey".to_owned());
+    /// assert_eq!(x.as_deref_mut().map(|x| {
+    ///     x.make_ascii_uppercase();
+    ///     x
+    /// }), Some("HEY".to_owned().as_mut_str()));
+    /// ```
     pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> {
         self.as_mut().map(|t| t.deref_mut())
     }
@@ -1199,6 +1223,13 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for Option<T> {
     /// Returns [`None`][Option::None].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let opt: Option<u32> = Option::default();
+    /// assert!(opt.is_none());
+    /// ```
     #[inline]
     fn default() -> Option<T> { None }
 }
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 6efeaf9..1dc6d54 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -233,7 +233,7 @@
 //! # type Field = i32;
 //! # struct Struct { field: Field }
 //! impl Struct {
-//!     fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field {
+//!     fn pin_get_field(self: Pin<&mut Self>) -> &mut Field {
 //!         // This is okay because `field` is never considered pinned.
 //!         unsafe { &mut self.get_unchecked_mut().field }
 //!     }
@@ -257,7 +257,7 @@
 //! # type Field = i32;
 //! # struct Struct { field: Field }
 //! impl Struct {
-//!     fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> {
+//!     fn pin_get_field(self: Pin<&mut Self>) -> Pin<&mut Field> {
 //!         // This is okay because `field` is pinned when `self` is.
 //!         unsafe { self.map_unchecked_mut(|s| &mut s.field) }
 //!     }
@@ -462,7 +462,7 @@
     /// can ignore the pinning invariants when unwrapping it.
     ///
     /// [`Unpin`]: ../../std/marker/trait.Unpin.html
-    #[unstable(feature = "pin_into_inner", issue = "60245")]
+    #[stable(feature = "pin_into_inner", since = "1.39.0")]
     #[inline(always)]
     pub fn into_inner(pin: Pin<P>) -> P {
         pin.pointer
@@ -549,7 +549,7 @@
     /// ruled out by the contract of `Pin::new_unchecked`.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn as_ref(self: &Pin<P>) -> Pin<&P::Target> {
+    pub fn as_ref(&self) -> Pin<&P::Target> {
         unsafe { Pin::new_unchecked(&*self.pointer) }
     }
 
@@ -569,7 +569,7 @@
     ///
     /// [`Unpin`]: ../../std/marker/trait.Unpin.html
     /// [`Pin::into_inner`]: #method.into_inner
-    #[unstable(feature = "pin_into_inner", issue = "60245")]
+    #[stable(feature = "pin_into_inner", since = "1.39.0")]
     #[inline(always)]
     pub unsafe fn into_inner_unchecked(pin: Pin<P>) -> P {
         pin.pointer
@@ -584,9 +584,30 @@
     /// the pointee cannot move after `Pin<Pointer<T>>` got created.
     /// "Malicious" implementations of `Pointer::DerefMut` are likewise
     /// ruled out by the contract of `Pin::new_unchecked`.
+    ///
+    /// This method is useful when doing multiple calls to functions that consume the pinned type.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::pin::Pin;
+    ///
+    /// # struct Type {}
+    /// impl Type {
+    ///     fn method(self: Pin<&mut Self>) {
+    ///         // do something
+    ///     }
+    ///
+    ///     fn call_method_twice(mut self: Pin<&mut Self>) {
+    ///         // `method` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`.
+    ///         self.as_mut().method();
+    ///         self.as_mut().method();
+    ///     }
+    /// }
+    /// ```
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn as_mut(self: &mut Pin<P>) -> Pin<&mut P::Target> {
+    pub fn as_mut(&mut self) -> Pin<&mut P::Target> {
         unsafe { Pin::new_unchecked(&mut *self.pointer) }
     }
 
@@ -596,7 +617,7 @@
     /// run before being overwritten, so no pinning guarantee is violated.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn set(self: &mut Pin<P>, value: P::Target)
+    pub fn set(&mut self, value: P::Target)
     where
         P::Target: Sized,
     {
@@ -621,7 +642,7 @@
     ///
     /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning
     #[stable(feature = "pin", since = "1.33.0")]
-    pub unsafe fn map_unchecked<U, F>(self: Pin<&'a T>, func: F) -> Pin<&'a U> where
+    pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U> where
         F: FnOnce(&T) -> &U,
     {
         let pointer = &*self.pointer;
@@ -648,7 +669,7 @@
     /// ["pinning projections"]: ../../std/pin/index.html#projections-and-structural-pinning
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn get_ref(self: Pin<&'a T>) -> &'a T {
+    pub fn get_ref(self) -> &'a T {
         self.pointer
     }
 }
@@ -657,7 +678,7 @@
     /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn into_ref(self: Pin<&'a mut T>) -> Pin<&'a T> {
+    pub fn into_ref(self) -> Pin<&'a T> {
         Pin { pointer: self.pointer }
     }
 
@@ -672,7 +693,7 @@
     /// with the same lifetime as the original `Pin`.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn get_mut(self: Pin<&'a mut T>) -> &'a mut T
+    pub fn get_mut(self) -> &'a mut T
         where T: Unpin,
     {
         self.pointer
@@ -690,7 +711,7 @@
     /// instead.
     #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub unsafe fn get_unchecked_mut(self: Pin<&'a mut T>) -> &'a mut T {
+    pub unsafe fn get_unchecked_mut(self) -> &'a mut T {
         self.pointer
     }
 
@@ -710,7 +731,7 @@
     ///
     /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning
     #[stable(feature = "pin", since = "1.33.0")]
-    pub unsafe fn map_unchecked_mut<U, F>(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where
+    pub unsafe fn map_unchecked_mut<U, F>(self, func: F) -> Pin<&'a mut U> where
         F: FnOnce(&mut T) -> &mut U,
     {
         let pointer = Pin::get_unchecked_mut(self);
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index f5fbd1a..13ccc9b 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -1042,7 +1042,7 @@
         (self as *const u8) == null()
     }
 
-    /// Cast to a pointer to a different type
+    /// Casts to a pointer of another type.
     #[stable(feature = "ptr_cast", since = "1.38.0")]
     #[inline]
     pub const fn cast<U>(self) -> *const U {
@@ -1726,7 +1726,7 @@
         (self as *mut u8) == null_mut()
     }
 
-    /// Cast to a pointer to a different type
+    /// Casts to a pointer of another type.
     #[stable(feature = "ptr_cast", since = "1.38.0")]
     #[inline]
     pub const fn cast<U>(self) -> *mut U {
diff --git a/src/libcore/ptr/non_null.rs b/src/libcore/ptr/non_null.rs
index ad3d1ce..7dcd57f 100644
--- a/src/libcore/ptr/non_null.rs
+++ b/src/libcore/ptr/non_null.rs
@@ -125,7 +125,7 @@
         &mut *self.as_ptr()
     }
 
-    /// Cast to a pointer of another type
+    /// Casts to a pointer of another type.
     #[stable(feature = "nonnull_cast", since = "1.27.0")]
     #[inline]
     pub const fn cast<U>(self) -> NonNull<U> {
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 8c60a9c..ed40a5f 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -820,6 +820,87 @@
     }
 }
 
+impl<T: Copy, E> Result<&T, E> {
+    /// Maps a `Result<&T, E>` to a `Result<T, E>` by copying the contents of the
+    /// `Ok` part.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_copied)]
+    /// let val = 12;
+    /// let x: Result<&i32, i32> = Ok(&val);
+    /// assert_eq!(x, Ok(&12));
+    /// let copied = x.copied();
+    /// assert_eq!(copied, Ok(12));
+    /// ```
+    #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")]
+    pub fn copied(self) -> Result<T, E> {
+        self.map(|&t| t)
+    }
+}
+
+impl<T: Copy, E> Result<&mut T, E> {
+    /// Maps a `Result<&mut T, E>` to a `Result<T, E>` by copying the contents of the
+    /// `Ok` part.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_copied)]
+    /// let mut val = 12;
+    /// let x: Result<&mut i32, i32> = Ok(&mut val);
+    /// assert_eq!(x, Ok(&mut 12));
+    /// let copied = x.copied();
+    /// assert_eq!(copied, Ok(12));
+    /// ```
+    #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")]
+    pub fn copied(self) -> Result<T, E> {
+        self.map(|&mut t| t)
+    }
+}
+
+impl<T: Clone, E> Result<&T, E> {
+    /// Maps a `Result<&T, E>` to a `Result<T, E>` by cloning the contents of the
+    /// `Ok` part.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_cloned)]
+    /// let val = 12;
+    /// let x: Result<&i32, i32> = Ok(&val);
+    /// assert_eq!(x, Ok(&12));
+    /// let cloned = x.cloned();
+    /// assert_eq!(cloned, Ok(12));
+    /// ```
+    #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")]
+    pub fn cloned(self) -> Result<T, E> {
+        self.map(|t| t.clone())
+    }
+}
+
+impl<T: Clone, E> Result<&mut T, E> {
+    /// Maps a `Result<&mut T, E>` to a `Result<T, E>` by cloning the contents of the
+    /// `Ok` part.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_cloned)]
+    /// let mut val = 12;
+    /// let x: Result<&mut i32, i32> = Ok(&mut val);
+    /// assert_eq!(x, Ok(&mut 12));
+    /// let cloned = x.cloned();
+    /// assert_eq!(cloned, Ok(12));
+    /// ```
+    #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")]
+    pub fn cloned(self) -> Result<T, E> {
+        self.map(|t| t.clone())
+    }
+}
+
+
 impl<T, E: fmt::Debug> Result<T, E> {
     /// Unwraps a result, yielding the content of an [`Ok`].
     ///
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 752c372..5e5b559 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3558,7 +3558,7 @@
     /// A string is a sequence of bytes. `start` in this context means the first
     /// position of that byte string; for a left-to-right language like English or
     /// Russian, this will be left side, and for right-to-left languages like
-    /// like Arabic or Hebrew, this will be the right side.
+    /// Arabic or Hebrew, this will be the right side.
     ///
     /// # Examples
     ///
@@ -3595,7 +3595,7 @@
     /// A string is a sequence of bytes. `end` in this context means the last
     /// position of that byte string; for a left-to-right language like English or
     /// Russian, this will be right side, and for right-to-left languages like
-    /// like Arabic or Hebrew, this will be the left side.
+    /// Arabic or Hebrew, this will be the left side.
     ///
     /// # Examples
     ///
@@ -3762,7 +3762,7 @@
     /// A string is a sequence of bytes. `start` in this context means the first
     /// position of that byte string; for a left-to-right language like English or
     /// Russian, this will be left side, and for right-to-left languages like
-    /// like Arabic or Hebrew, this will be the right side.
+    /// Arabic or Hebrew, this will be the right side.
     ///
     /// # Examples
     ///
@@ -3801,7 +3801,7 @@
     /// A string is a sequence of bytes. `end` in this context means the last
     /// position of that byte string; for a left-to-right language like English or
     /// Russian, this will be right side, and for right-to-left languages like
-    /// like Arabic or Hebrew, this will be the left side.
+    /// Arabic or Hebrew, this will be the left side.
     ///
     /// # Examples
     ///
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 8dfb19f..c9ccef9 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -124,28 +124,31 @@
 
 use crate::hint::spin_loop;
 
-/// Signals the processor that it is entering a busy-wait spin-loop.
+/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
 ///
 /// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
 /// power or switching hyper-threads.
 ///
-/// This function is different than [`std::thread::yield_now`] which directly yields to the
-/// system's scheduler, whereas `spin_loop_hint` only signals the processor that it is entering a
-/// busy-wait spin-loop without yielding control to the system's scheduler.
+/// This function is different from [`std::thread::yield_now`] which directly yields to the
+/// system's scheduler, whereas `spin_loop_hint` does not interact with the operating system.
 ///
-/// Using a busy-wait spin-loop with `spin_loop_hint` is ideally used in situations where a
-/// contended lock is held by another thread executed on a different CPU and where the waiting
-/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's
-/// scheduler, no overhead for switching threads occurs. However, if the thread holding the
-/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice
-/// before switching to the thread that holds the lock. If the contending lock is held by a thread
-/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to
-/// use [`std::thread::yield_now`].
+/// Spin locks can be very efficient for short lock durations because they do not involve context
+/// switches or interaction with the operating system. For long lock durations they become wasteful
+/// however because they use CPU cycles for the entire lock duration, and using a
+/// [`std::sync::Mutex`] is likely the better approach. If actively spinning for a long time is
+/// required, e.g. because code polls a non-blocking API, calling [`std::thread::yield_now`]
+/// or [`std::thread::sleep`] may be the best option.
+///
+/// **Note**: Spin locks are based on the underlying assumption that another thread will release
+/// the lock 'soon'. In order for this to work, that other thread must run on a different CPU or
+/// core (at least potentially). Spin locks do not work efficiently on single CPU / core platforms.
 ///
 /// **Note**: On platforms that do not support receiving spin-loop hints this function does not
 /// do anything at all.
 ///
 /// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html
+/// [`std::thread::sleep`]: ../../../std/thread/fn.sleep.html
+/// [`std::sync::Mutex`]: ../../../std/sync/struct.Mutex.html
 #[inline]
 #[stable(feature = "spin_loop_hint", since = "1.24.0")]
 pub fn spin_loop_hint() {
@@ -979,9 +982,8 @@
     /// let some_ptr  = AtomicPtr::new(ptr);
     ///
     /// let other_ptr   = &mut 10;
-    /// let another_ptr = &mut 10;
     ///
-    /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed);
+    /// let value = some_ptr.compare_and_swap(ptr, other_ptr, Ordering::Relaxed);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1021,9 +1023,8 @@
     /// let some_ptr  = AtomicPtr::new(ptr);
     ///
     /// let other_ptr   = &mut 10;
-    /// let another_ptr = &mut 10;
     ///
-    /// let value = some_ptr.compare_exchange(other_ptr, another_ptr,
+    /// let value = some_ptr.compare_exchange(ptr, other_ptr,
     ///                                       Ordering::SeqCst, Ordering::Relaxed);
     /// ```
     #[inline]
diff --git a/src/libcore/tests/bool.rs b/src/libcore/tests/bool.rs
new file mode 100644
index 0000000..0f1e6e8
--- /dev/null
+++ b/src/libcore/tests/bool.rs
@@ -0,0 +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));
+}
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 3a4f768..c9096b7 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -58,6 +58,62 @@
 }
 
 #[test]
+fn test_cmp_by() {
+    use core::cmp::Ordering;
+
+    let f = |x: i32, y: i32| (x * x).cmp(&y);
+    let xs = || [1, 2, 3, 4].iter().copied();
+    let ys = || [1, 4, 16].iter().copied();
+
+    assert_eq!(xs().cmp_by(ys(), f), Ordering::Less);
+    assert_eq!(ys().cmp_by(xs(), f), Ordering::Greater);
+    assert_eq!(xs().cmp_by(xs().map(|x| x * x), f), Ordering::Equal);
+    assert_eq!(xs().rev().cmp_by(ys().rev(), f), Ordering::Greater);
+    assert_eq!(xs().cmp_by(ys().rev(), f), Ordering::Less);
+    assert_eq!(xs().cmp_by(ys().take(2), f), Ordering::Greater);
+}
+
+#[test]
+fn test_partial_cmp_by() {
+    use core::cmp::Ordering;
+    use core::f64;
+
+    let f = |x: i32, y: i32| (x * x).partial_cmp(&y);
+    let xs = || [1, 2, 3, 4].iter().copied();
+    let ys = || [1, 4, 16].iter().copied();
+
+    assert_eq!(xs().partial_cmp_by(ys(), f), Some(Ordering::Less));
+    assert_eq!(ys().partial_cmp_by(xs(), f), Some(Ordering::Greater));
+    assert_eq!(xs().partial_cmp_by(xs().map(|x| x * x), f), Some(Ordering::Equal));
+    assert_eq!(xs().rev().partial_cmp_by(ys().rev(), f), Some(Ordering::Greater));
+    assert_eq!(xs().partial_cmp_by(xs().rev(), f), Some(Ordering::Less));
+    assert_eq!(xs().partial_cmp_by(ys().take(2), f), Some(Ordering::Greater));
+
+    let f = |x: f64, y: f64| (x * x).partial_cmp(&y);
+    let xs = || [1.0, 2.0, 3.0, 4.0].iter().copied();
+    let ys = || [1.0, 4.0, f64::NAN, 16.0].iter().copied();
+
+    assert_eq!(xs().partial_cmp_by(ys(), f), None);
+    assert_eq!(ys().partial_cmp_by(xs(), f), Some(Ordering::Greater));
+}
+
+#[test]
+fn test_eq_by() {
+    let f = |x: i32, y: i32| x * x == y;
+    let xs = || [1, 2, 3, 4].iter().copied();
+    let ys = || [1, 4, 9, 16].iter().copied();
+
+    assert!(xs().eq_by(ys(), f));
+    assert!(!ys().eq_by(xs(), f));
+    assert!(!xs().eq_by(xs(), f));
+    assert!(!ys().eq_by(ys(), f));
+
+    assert!(!xs().take(3).eq_by(ys(), f));
+    assert!(!xs().eq_by(ys().take(3), f));
+    assert!(xs().take(3).eq_by(ys().take(3), f));
+}
+
+#[test]
 fn test_counter_from_iter() {
     let it = (0..).step_by(5).take(10);
     let xs: Vec<isize> = FromIterator::from_iter(it);
@@ -330,6 +386,23 @@
 }
 
 #[test]
+fn test_iterator_step_by_nth_try_fold() {
+    let mut it = (0..).step_by(10);
+    assert_eq!(it.try_fold(0, i8::checked_add), None);
+    assert_eq!(it.next(), Some(60));
+    assert_eq!(it.try_fold(0, i8::checked_add), None);
+    assert_eq!(it.next(), Some(90));
+
+    let mut it = (100..).step_by(10);
+    assert_eq!(it.try_fold(50, i8::checked_add), None);
+    assert_eq!(it.next(), Some(110));
+
+    let mut it = (100..=100).step_by(10);
+    assert_eq!(it.next(), Some(100));
+    assert_eq!(it.try_fold(0, i8::checked_add), Some(0));
+}
+
+#[test]
 fn test_iterator_step_by_nth_back() {
     let mut it = (0..16).step_by(5);
     assert_eq!(it.nth_back(0), Some(15));
@@ -355,6 +428,24 @@
 }
 
 #[test]
+fn test_iterator_step_by_nth_try_rfold() {
+    let mut it = (0..100).step_by(10);
+    assert_eq!(it.try_rfold(0, i8::checked_add), None);
+    assert_eq!(it.next_back(), Some(70));
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.try_rfold(0, i8::checked_add), None);
+    assert_eq!(it.next_back(), Some(30));
+
+    let mut it = (0..100).step_by(10);
+    assert_eq!(it.try_rfold(50, i8::checked_add), None);
+    assert_eq!(it.next_back(), Some(80));
+
+    let mut it = (100..=100).step_by(10);
+    assert_eq!(it.next_back(), Some(100));
+    assert_eq!(it.try_fold(0, i8::checked_add), Some(0));
+}
+
+#[test]
 #[should_panic]
 fn test_iterator_step_by_zero() {
     let mut it = (0..).step_by(0);
@@ -1689,6 +1780,12 @@
 }
 
 #[test]
+fn test_rev_rposition() {
+    let v = [0, 0, 1, 1];
+    assert_eq!(v.iter().rev().rposition(|&x| x == 1), Some(1));
+}
+
+#[test]
 #[should_panic]
 fn test_rposition_panic() {
     let v: [(Box<_>, Box<_>); 4] =
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index a3b108b..050195c 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -1,3 +1,4 @@
+#![feature(bool_to_option)]
 #![feature(bound_cloned)]
 #![feature(box_syntax)]
 #![feature(cell_update)]
@@ -32,6 +33,7 @@
 #![feature(const_fn)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_is_partitioned)]
+#![feature(iter_order_by)]
 
 extern crate test;
 
@@ -40,6 +42,7 @@
 mod array;
 mod ascii;
 mod atomic;
+mod bool;
 mod cell;
 mod char;
 mod clone;
diff --git a/src/libcore/unicode/mod.rs b/src/libcore/unicode/mod.rs
index 272727d..a3ec9fd 100644
--- a/src/libcore/unicode/mod.rs
+++ b/src/libcore/unicode/mod.rs
@@ -13,8 +13,3 @@
 pub mod conversions {
     pub use crate::unicode::tables::conversions::{to_lower, to_upper};
 }
-
-// For use in libsyntax
-pub mod property {
-    pub use crate::unicode::tables::property::Pattern_White_Space;
-}
diff --git a/src/libcore/unicode/printable.py b/src/libcore/unicode/printable.py
index 748917f..4e8b4ec 100644
--- a/src/libcore/unicode/printable.py
+++ b/src/libcore/unicode/printable.py
@@ -60,7 +60,7 @@
         yield Codepoint(codepoint, class_)
         prev_codepoint = codepoint
 
-    if class_first != None:
+    if class_first is not None:
         raise ValueError("Missing Last after First")
 
     for c in range(prev_codepoint + 1, NUM_CODEPOINTS):
diff --git a/src/libcore/unicode/tables.rs b/src/libcore/unicode/tables.rs
index 3fae3a4..5b5be48 100644
--- a/src/libcore/unicode/tables.rs
+++ b/src/libcore/unicode/tables.rs
@@ -890,384 +890,9 @@
         Uppercase_table.lookup(c)
     }
 
-    const XID_Continue_table: &super::BoolTrie = &super::BoolTrie {
-        r1: [
-            0x03ff000000000000, 0x07fffffe87fffffe, 0x04a0040000000000, 0xff7fffffff7fffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3,
-            0xffffffffffffffff, 0xb8dfffffffffffff, 0xfffffffbffffd7c0, 0xffbfffffffffffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffcfb, 0xffffffffffffffff,
-            0xfffeffffffffffff, 0xffffffff027fffff, 0xbffffffffffe01ff, 0x000787ffffff00b6,
-            0xffffffff07ff0000, 0xffffc3ffffffffff, 0xffffffffffffffff, 0x9ffffdff9fefffff,
-            0xffffffffffff0000, 0xffffffffffffe7ff, 0x0003ffffffffffff, 0x243fffffffffffff
-        ],
-        r2: [
-            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
-            24, 25, 26, 27, 28, 29, 30, 31, 4, 32, 33, 34, 4, 4, 4, 4, 4, 35, 36, 37, 38, 39, 40,
-            41, 42, 4, 4, 4, 4, 4, 4, 4, 4, 43, 44, 45, 46, 47, 4, 48, 49, 50, 51, 52, 53, 54, 55,
-            56, 57, 58, 59, 60, 4, 61, 4, 62, 63, 64, 65, 66, 4, 4, 4, 67, 4, 4, 4, 4, 68, 69, 70,
-            71, 72, 73, 74, 75, 76, 77, 78, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-            60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-            60, 60, 60, 60, 60, 79, 80, 4, 81, 82, 83, 84, 85, 60, 60, 60, 60, 60, 60, 60, 60, 86,
-            42, 87, 88, 89, 4, 90, 91, 60, 60, 60, 60, 60, 60, 60, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 52, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 93, 94, 4, 4, 4, 4, 95, 96, 4, 97, 98, 4, 99, 100, 101, 62, 4, 102, 103,
-            104, 4, 105, 106, 107, 4, 108, 109, 110, 4, 111, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 112, 113, 60, 60, 60, 60, 60, 60, 60,
-            60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-            60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-            60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-            60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-            60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-            60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 4, 4, 4, 4, 4, 103, 4, 114,
-            115, 116, 97, 117, 4, 118, 4, 4, 119, 120, 121, 122, 123, 124, 4, 125, 126, 127, 128,
-            129
-        ],
-        r3: &[
-            0x00003fffffffffff, 0x000007ff0fffffff, 0x3fdfffff00000000, 0xfffffffbfff80000,
-            0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x5003ffcfb080799f,
-            0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0xfe00ffcf00013bbf,
-            0xf3edfdfffff99fee, 0x0002ffcfb0c0399f, 0xc3ffc718d63dc7ec, 0x0000ffc000813dc7,
-            0xe3fffdfffffddfff, 0x0000ffcf07603ddf, 0xf3effdfffffddfef, 0x0006ffcf40603ddf,
-            0xfffffffffffddfef, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f,
-            0x07fffffffffffffe, 0x0000000003ff7fff, 0x3fffffaffffff7d6, 0x00000000f3ff3f5f,
-            0xc2a003ff03000001, 0xfffe1ffffffffeff, 0x1ffffffffeffffdf, 0x0000000000000040,
-            0xffffffffffff03ff, 0xffffffff3fffffff, 0xf7ffffffffff20bf, 0xffffffff3d7f3dff,
-            0x7f3dffffffff3dff, 0xffffffffff7fff3d, 0xffffffffff3dffff, 0x0003fe00e7ffffff,
-            0xffffffff0000ffff, 0x3f3fffffffffffff, 0xfffffffffffffffe, 0xffff9fffffffffff,
-            0xffffffff07fffffe, 0x01ffc7ffffffffff, 0x001fffff001fdfff, 0x000ddfff000fffff,
-            0x000003ff308fffff, 0xffffffff03ff3800, 0x01ffffffffffffff, 0xffff07ffffffffff,
-            0x003fffffffffffff, 0x0fff0fff7fffffff, 0x001f3fffffffffc0, 0xffff0fffffffffff,
-            0x0000000007ff03ff, 0xffffffff0fffffff, 0x9fffffff7fffffff, 0x3fff008003ff03ff,
-            0x0000000000000000, 0x000ff80003ff0fff, 0x000fffffffffffff, 0x00ffffffffffffff,
-            0x3fffffffffffe3ff, 0xe7ffffffffff01ff, 0x07fffffffff70000, 0xfbffffffffffffff,
-            0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc,
-            0x8000000000000000, 0x8002000000100001, 0x000000001fff0000, 0x0001ffe21fff0000,
-            0xf3fffd503f2ffc84, 0xffffffff000043e0, 0x00000000000001ff, 0xffff7fffffffffff,
-            0xffffffff7fffffff, 0x000ff81fffffffff, 0xffff20bfffffffff, 0x800080ffffffffff,
-            0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, 0x1f3efffe000000e0, 0xfffffffee67fffff,
-            0xf7ffffffffffffff, 0xfffeffffffffffe0, 0x07ffffff00007fff, 0xffff000000000000,
-            0x0000ffffffffffff, 0x0000000000001fff, 0x3fffffffffff0000, 0x00000fffffff1fff,
-            0xbff0ffffffffffff, 0x0003ffffffffffff, 0xfffffffcff800000, 0xfffffffffffff9ff,
-            0xff8000000000007c, 0x000000ffffffffff, 0xe8ffffff03ff003f, 0xffff3fffffffffff,
-            0x1fffffff000fffff, 0x7fffffff03ff8001, 0x007fffffffffffff, 0xfc7fffff03ff3fff,
-            0x007cffff38000007, 0xffff7f7f007e7e7e, 0xffff00fff7ffffff, 0x03ff37ffffffffff,
-            0xffff000fffffffff, 0x0ffffffffffff87f, 0x0000000003ffffff, 0x5f7ffdffe0f8007f,
-            0xffffffffffffffdb, 0xfffffffffff80000, 0xfffffff03fffffff, 0x3fffffffffffffff,
-            0xffffffffffff0000, 0xfffffffffffcffff, 0x03ff0000000000ff, 0x0018ffff0000ffff,
-            0xaa8a00000000e000, 0x1fffffffffffffff, 0x87fffffe03ff0000, 0xffffffc007fffffe,
-            0x7fffffffffffffff, 0x000000001cfcfcfc
-        ],
-        r4: [
-            0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13,
-            14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
-        ],
-        r5: &[
-            0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 14, 15, 16, 4, 4, 2, 2, 2,
-            2, 17, 18, 4, 4, 19, 20, 21, 22, 23, 4, 24, 4, 25, 26, 27, 28, 29, 30, 31, 4, 2, 32, 33,
-            33, 34, 4, 4, 4, 4, 4, 4, 4, 35, 36, 4, 37, 2, 38, 3, 39, 40, 41, 2, 42, 43, 4, 44, 45,
-            46, 47, 4, 4, 2, 48, 2, 49, 4, 4, 50, 51, 2, 52, 53, 54, 55, 4, 4, 4, 3, 4, 56, 57, 4,
-            4, 58, 59, 60, 61, 62, 53, 4, 4, 4, 4, 63, 64, 65, 4, 66, 67, 68, 4, 4, 4, 4, 37, 4, 4,
-            4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 4, 2, 70, 2, 2, 2, 71, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 70, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 2, 2, 2, 2, 2, 2, 2, 2, 53, 73, 4, 74, 17, 75, 76, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
-            4, 4, 2, 77, 78, 79, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 80, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 21, 81, 2, 2, 2, 2,
-            2, 82, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 83, 84, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 85, 86, 4, 4, 87, 4, 4, 4, 4, 4, 4, 2, 88, 89, 90, 91, 92, 2, 2, 2, 2, 93, 94, 95,
-            96, 97, 98, 4, 4, 4, 4, 4, 4, 4, 4, 99, 100, 101, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 102, 4, 4, 4, 103, 104, 4, 4, 4, 4, 4, 105, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 106, 2, 107, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 108, 109, 110, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 111, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 112, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 113, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 114, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 115, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
-        ],
-        r6: &[
-            0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff,
-            0x0000000000000000, 0x001fffffffffffff, 0x2000000000000000, 0xffffffff1fffffff,
-            0x000000010001ffff, 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff,
-            0x00000000003eff0f, 0xffff03ff3fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff,
-            0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f,
-            0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff,
-            0xc0ffffffffffffff, 0x873ffffffeeff06f, 0x1fffffff00000000, 0x000000001fffffff,
-            0x0000007ffffffeff, 0x003fffffffffffff, 0x0007ffff003fffff, 0x000000000003ffff,
-            0x00000000000001ff, 0x0007ffffffffffff, 0x03ff00ffffffffff, 0xffff00801fffffff,
-            0x000000000001ffff, 0x007fffff00000000, 0x8000ffc00000007f, 0x03ff01ffffff0000,
-            0xffdfffffffffffff, 0x004fffffffff0070, 0x0000000017ff1e1f, 0x40fffffffffbffff,
-            0xffff01ffbfffbd7f, 0x03ff07ffffffffff, 0xfbedfdfffff99fef, 0x001f1fcfe081399f,
-            0x00000000c3ff07ff, 0x0000000003ff00bf, 0xff3fffffffffffff, 0x000000003f000001,
-            0x0000000003ff0011, 0x01ffffffffffffff, 0x00000000000003ff, 0x03ff0fffe7ffffff,
-            0xffffffff00000000, 0x800003ffffffffff, 0xfffffcff00000000, 0x0000001bfcffffff,
-            0x7fffffffffffffff, 0xffffffffffff0080, 0x0000000023ffffff, 0xff7ffffffffffdff,
-            0xfffc000003ff0001, 0x007ffefffffcffff, 0xb47ffffffffffb7f, 0xfffffdbf03ff00ff,
-            0x000003ff01fb7fff, 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f,
-            0x000000000000007f, 0x000003ff7fffffff, 0x001f3fffffff0000, 0xe0fffff803ff000f,
-            0x000000000000ffff, 0xffffffffffff87ff, 0x00000000ffff80ff, 0x0000000b00000000,
-            0x00ffffffffffffff, 0xffff00f000070000, 0x0fffffffffffffff, 0x1fff07ffffffffff,
-            0x0000000063ff01ff, 0xf807e3e000000000, 0x00003c0000000fe7, 0x000000000000001c,
-            0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf,
-            0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff,
-            0xffff7fffffff7fff, 0xfffffdfffffffdff, 0xffffffffffffcff7, 0xf87fffffffffffff,
-            0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x3fff1fffffffffff,
-            0x00000000000043ff, 0x03ffffffffffffff, 0x00000000007f001f, 0x0000000003ff0fff,
-            0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff,
-            0xffff0003ffffffff, 0x00000001ffffffff, 0x000000003fffffff, 0x0000ffffffffffff
-        ],
-    };
-
-    pub fn XID_Continue(c: char) -> bool {
-        XID_Continue_table.lookup(c)
-    }
-
-    const XID_Start_table: &super::BoolTrie = &super::BoolTrie {
-        r1: [
-            0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3,
-            0x0000000000000000, 0xb8df000000000000, 0xfffffffbffffd740, 0xffbfffffffffffff,
-            0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffc03, 0xffffffffffffffff,
-            0xfffeffffffffffff, 0xffffffff027fffff, 0x00000000000001ff, 0x000787ffffff0000,
-            0xffffffff00000000, 0xfffec000000007ff, 0xffffffffffffffff, 0x9c00c060002fffff,
-            0x0000fffffffd0000, 0xffffffffffffe000, 0x0002003fffffffff, 0x043007fffffffc00
-        ],
-        r2: [
-            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
-            24, 23, 25, 26, 27, 28, 29, 3, 30, 31, 32, 33, 34, 34, 34, 34, 34, 35, 36, 37, 38, 39,
-            40, 41, 42, 34, 34, 34, 34, 34, 34, 34, 34, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-            54, 55, 56, 57, 58, 59, 60, 3, 61, 62, 63, 64, 65, 66, 67, 68, 34, 34, 34, 3, 34, 34,
-            34, 34, 69, 70, 71, 72, 3, 73, 74, 3, 75, 76, 77, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-            3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 78,
-            79, 34, 80, 81, 82, 83, 84, 3, 3, 3, 3, 3, 3, 3, 3, 85, 42, 86, 87, 88, 34, 89, 90, 3,
-            3, 3, 3, 3, 3, 3, 3, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 53, 3, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 91, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 92, 93, 34, 34, 34, 34, 94,
-            95, 96, 91, 97, 34, 98, 99, 100, 48, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
-            111, 112, 34, 113, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-            34, 34, 34, 114, 115, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-            3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-            3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-            3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-            3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 34, 34, 34, 34, 34,
-            116, 34, 117, 118, 119, 120, 121, 34, 122, 34, 34, 123, 124, 125, 126, 3, 127, 34, 128,
-            129, 130, 131, 132
-        ],
-        r3: &[
-            0x00000110043fffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0x0000000000000000,
-            0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x10030003b0004000,
-            0x036dfdfffff987e0, 0x001c00005e000000, 0x23edfdfffffbbfe0, 0x0200000300010000,
-            0x23edfdfffff99fe0, 0x00020003b0000000, 0x03ffc718d63dc7e8, 0x0000000000010000,
-            0x23fffdfffffddfe0, 0x0000000307000000, 0x23effdfffffddfe1, 0x0006000340000000,
-            0x27fffffffffddfe0, 0xfc00000380704000, 0x2ffbfffffc7fffe0, 0x000000000000007f,
-            0x0005fffffffffffe, 0x2005ffaffffff7d6, 0x00000000f000005f, 0x0000000000000001,
-            0x00001ffffffffeff, 0x0000000000001f00, 0x800007ffffffffff, 0xffe1c0623c3f0000,
-            0xffffffff00004003, 0xf7ffffffffff20bf, 0xffffffffffffffff, 0xffffffff3d7f3dff,
-            0x7f3dffffffff3dff, 0xffffffffff7fff3d, 0xffffffffff3dffff, 0x0000000007ffffff,
-            0xffffffff0000ffff, 0x3f3fffffffffffff, 0xfffffffffffffffe, 0xffff9fffffffffff,
-            0xffffffff07fffffe, 0x01ffc7ffffffffff, 0x0003ffff0003dfff, 0x0001dfff0003ffff,
-            0x000fffffffffffff, 0x0000000010800000, 0xffffffff00000000, 0x01ffffffffffffff,
-            0xffff05ffffffffff, 0x003fffffffffffff, 0x000000007fffffff, 0x001f3fffffff0000,
-            0xffff0fffffffffff, 0x00000000000003ff, 0xffffffff007fffff, 0x00000000001fffff,
-            0x0000008000000000, 0x000fffffffffffe0, 0x0000000000000fe0, 0xfc00c001fffffff8,
-            0x0000003fffffffff, 0x0000000fffffffff, 0x3ffffffffc00e000, 0xe7ffffffffff01ff,
-            0x046fde0000000000, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff,
-            0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000, 0xf3fffd503f2ffc84,
-            0xffffffff000043e0, 0x00000000000001ff, 0xffff7fffffffffff, 0xffffffff7fffffff,
-            0x000c781fffffffff, 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff,
-            0x000000007f7f7f7f, 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff,
-            0xfffeffffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x0000ffffffffffff,
-            0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x80007fffffffffff,
-            0xffffffff3fffffff, 0xfffffffcff800000, 0xfffffffffffff9ff, 0xff8000000000007c,
-            0x00000007fffff7bb, 0x000ffffffffffffc, 0x68fc000000000000, 0xffff003ffffffc00,
-            0x1fffffff0000007f, 0x0007fffffffffff0, 0x7c00ffdf00008000, 0x000001ffffffffff,
-            0xc47fffff00000ff7, 0x3e62ffffffffffff, 0x001c07ff38000005, 0xffff7f7f007e7e7e,
-            0xffff00fff7ffffff, 0x00000007ffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f,
-            0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffa0f8007f, 0xffffffffffffffdb,
-            0x0003ffffffffffff, 0xfffffffffff80000, 0xfffffff03fffffff, 0x3fffffffffffffff,
-            0xffffffffffff0000, 0xfffffffffffcffff, 0x03ff0000000000ff, 0xaa8a000000000000,
-            0x1fffffffffffffff, 0x07fffffe00000000, 0xffffffc007fffffe, 0x7fffffff3fffffff,
-            0x000000001cfcfcfc
-        ],
-        r4: [
-            0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13,
-            14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
-        ],
-        r5: &[
-            0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2,
-            2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32,
-            32, 15, 4, 4, 4, 4, 4, 4, 4, 33, 34, 4, 35, 36, 4, 37, 38, 39, 40, 41, 42, 43, 4, 44,
-            20, 45, 46, 4, 4, 5, 47, 48, 49, 4, 4, 50, 51, 48, 52, 53, 4, 54, 4, 4, 4, 55, 4, 56,
-            57, 4, 4, 58, 59, 60, 61, 62, 63, 4, 4, 4, 4, 64, 65, 66, 4, 67, 68, 69, 4, 4, 4, 4, 70,
-            4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 71, 4, 2, 50, 2, 2, 2, 72, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 50, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 73, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 63, 20, 4, 74, 48, 75, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 2, 4, 4, 2, 76, 77, 78, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 79, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 80, 2,
-            2, 2, 2, 2, 81, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 82, 83, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 84, 85, 86, 87, 88, 2, 2, 2, 2, 89, 90,
-            91, 92, 93, 94, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 95, 96, 4, 4, 4, 4, 4, 55, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 97, 2, 98, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 99, 100, 101, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 102, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 103,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 104, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 105, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
-        ],
-        r6: &[
-            0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff,
-            0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff,
-            0xffffe000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f,
-            0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff,
-            0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff,
-            0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff,
-            0x003ffffffeef0001, 0x1fffffff00000000, 0x000000001fffffff, 0x0000001ffffffeff,
-            0x003fffffffffffff, 0x0007ffff003fffff, 0x000000000003ffff, 0x00000000000001ff,
-            0x0007ffffffffffff, 0xffff00801fffffff, 0x000000000000003f, 0x007fffff00000000,
-            0x00fffffffffffff8, 0x0000fffffffffff8, 0x000001ffffff0000, 0x0000007ffffffff8,
-            0x0047ffffffff0010, 0x0007fffffffffff8, 0x000000001400001e, 0x00000ffffffbffff,
-            0xffff01ffbfffbd7f, 0x23edfdfffff99fe0, 0x00000003e0010000, 0x0000000080000780,
-            0x0000ffffffffffff, 0x00000000000000b0, 0x00007fffffffffff, 0x000000000f000000,
-            0x0000000000000010, 0x010007ffffffffff, 0x0000000007ffffff, 0x00000fffffffffff,
-            0xffffffff00000000, 0x80000000ffffffff, 0xfffffcff00000000, 0x0000000a0001ffff,
-            0x0407fffffffff801, 0xfffffffff0010000, 0x00000000200003ff, 0x01ffffffffffffff,
-            0x00007ffffffffdff, 0xfffc000000000001, 0x000000000000ffff, 0x0001fffffffffb7f,
-            0xfffffdbf00000040, 0x00000000010003ff, 0x0007ffff00000000, 0x0000000003ffffff,
-            0x000000000000000f, 0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f,
-            0x00000000000107ff, 0x00000000fff80000, 0x0000000b00000000, 0x00ffffffffffffff,
-            0xffff00f000070000, 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000003ff01ff,
-            0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf,
-            0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff,
-            0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, 0x3f801fffffffffff,
-            0x0000000000004000, 0x000000000000001f, 0x000000000000080f, 0x0af7fe96ffffffef,
-            0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff,
-            0x00000001ffffffff, 0x000000003fffffff
-        ],
-    };
-
-    pub fn XID_Start(c: char) -> bool {
-        XID_Start_table.lookup(c)
-    }
-
 }
 
 pub(crate) mod property {
-    const Pattern_White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie {
-        r1: &[
-            0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3
-        ],
-        r2: &[
-            0x0000000100003e00, 0x0000000000000000, 0x0000000000000020, 0x000003000000c000
-        ],
-    };
-
-    pub fn Pattern_White_Space(c: char) -> bool {
-        Pattern_White_Space_table.lookup(c)
-    }
-
     const White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie {
         r1: &[
             0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py
index 6de5d9e..89894f7 100755
--- a/src/libcore/unicode/unicode.py
+++ b/src/libcore/unicode/unicode.py
@@ -728,7 +728,7 @@
 
     yield "pub(crate) mod %s {\n" % mod
     for cat in sorted(category_subset):
-        if cat in ("Cc", "White_Space", "Pattern_White_Space"):
+        if cat in ("Cc", "White_Space"):
             generator = generate_small_bool_trie("%s_table" % cat, grouped_categories[cat])
         else:
             generator = generate_bool_trie("%s_table" % cat, grouped_categories[cat])
@@ -841,19 +841,18 @@
     unicode_data = load_unicode_data(get_path(UnicodeFiles.UNICODE_DATA))
     load_special_casing(get_path(UnicodeFiles.SPECIAL_CASING), unicode_data)
 
-    want_derived = {"XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase",
+    want_derived = {"Alphabetic", "Lowercase", "Uppercase",
                     "Cased", "Case_Ignorable", "Grapheme_Extend"}
     derived = load_properties(get_path(UnicodeFiles.DERIVED_CORE_PROPERTIES), want_derived)
 
     props = load_properties(get_path(UnicodeFiles.PROPS),
-                            {"White_Space", "Join_Control", "Noncharacter_Code_Point",
-                             "Pattern_White_Space"})
+                            {"White_Space", "Join_Control", "Noncharacter_Code_Point"})
 
     # Category tables
     for (name, categories, category_subset) in (
             ("general_category", unicode_data.general_categories, ["N", "Cc"]),
             ("derived_property", derived, want_derived),
-            ("property", props, ["White_Space", "Pattern_White_Space"])
+            ("property", props, ["White_Space"])
     ):
         for fragment in generate_property_module(name, categories, category_subset):
             buf.write(fragment)
diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml
index 82a9e34..fff4ec7 100644
--- a/src/libfmt_macros/Cargo.toml
+++ b/src/libfmt_macros/Cargo.toml
@@ -10,4 +10,4 @@
 
 [dependencies]
 syntax_pos = { path = "../libsyntax_pos" }
-
+rustc_lexer = { path = "../librustc_lexer" }
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 985abaf..f9c1be2 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -597,12 +597,11 @@
         }
     }
 
-    /// Parses a word starting at the current position. A word is considered to
-    /// be an alphabetic character followed by any number of alphanumeric
-    /// characters.
+    /// Parses a word starting at the current position. A word is the same as
+    /// Rust identifier, except that it can't start with `_` character.
     fn word(&mut self) -> &'a str {
         let start = match self.cur.peek() {
-            Some(&(pos, c)) if c.is_xid_start() => {
+            Some(&(pos, c)) if c != '_' && rustc_lexer::is_id_start(c) => {
                 self.cur.next();
                 pos
             }
@@ -611,7 +610,7 @@
             }
         };
         while let Some(&(pos, c)) = self.cur.peek() {
-            if c.is_xid_continue() {
+            if rustc_lexer::is_id_continue(c) {
                 self.cur.next();
             } else {
                 return &self.input[start..pos];
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 0222a3d..0834faf 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -15,13 +15,12 @@
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 jobserver = "0.1"
-lazy_static = "1.0.0"
 num_cpus = "1.0"
 scoped-tls = "1.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
 rustc-rayon = "0.2.0"
 rustc-rayon-core = "0.2.0"
-polonius-engine  = "0.9.0"
+polonius-engine  = "0.10.0"
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_target = { path = "../librustc_target" }
 rustc_macros = { path = "../librustc_macros" }
@@ -31,8 +30,8 @@
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 backtrace = "0.3.3"
-parking_lot = "0.7"
-byteorder = { version = "1.1", features = ["i128"]}
+parking_lot = "0.9"
+byteorder = { version = "1.3" }
 chalk-engine = { version = "0.9.0", default-features=false }
 rustc_fs_util = { path = "../librustc_fs_util" }
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index b3a561e..d4fc1b1 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -187,7 +187,7 @@
 
 unsafe trait ArenaField<'tcx>: Sized {
     /// Returns a specific arena to allocate from.
-    /// If None is returned, the DropArena will be used.
+    /// If `None` is returned, the `DropArena` will be used.
     fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>>;
 }
 
diff --git a/src/librustc/cfg/mod.rs b/src/librustc/cfg/mod.rs
deleted file mode 100644
index 88fc7fb..0000000
--- a/src/librustc/cfg/mod.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-//! Module that constructs a control-flow graph representing an item.
-//! Uses `Graph` as the underlying representation.
-
-use rustc_data_structures::graph::implementation as graph;
-use crate::ty::TyCtxt;
-use crate::hir;
-use crate::hir::def_id::DefId;
-
-mod construct;
-pub mod graphviz;
-
-pub struct CFG {
-    pub owner_def_id: DefId,
-    pub graph: CFGGraph,
-    pub entry: CFGIndex,
-    pub exit: CFGIndex,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq)]
-pub enum CFGNodeData {
-    AST(hir::ItemLocalId),
-    Entry,
-    Exit,
-    Dummy,
-    Unreachable,
-}
-
-impl CFGNodeData {
-    pub fn id(&self) -> hir::ItemLocalId {
-        if let CFGNodeData::AST(id) = *self {
-            id
-        } else {
-            hir::DUMMY_ITEM_LOCAL_ID
-        }
-    }
-}
-
-#[derive(Debug)]
-pub struct CFGEdgeData {
-    pub exiting_scopes: Vec<hir::ItemLocalId>
-}
-
-pub type CFGIndex = graph::NodeIndex;
-
-pub type CFGGraph = graph::Graph<CFGNodeData, CFGEdgeData>;
-
-pub type CFGNode = graph::Node<CFGNodeData>;
-
-pub type CFGEdge = graph::Edge<CFGEdgeData>;
-
-impl CFG {
-    pub fn new(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG {
-        construct::construct(tcx, body)
-    }
-
-    pub fn node_is_reachable(&self, id: hir::ItemLocalId) -> bool {
-        self.graph.depth_traverse(self.entry, graph::OUTGOING)
-                  .any(|idx| self.graph.node_data(idx).id() == id)
-    }
-}
diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs
index 2d09013..eee3384 100644
--- a/src/librustc/error_codes.rs
+++ b/src/librustc/error_codes.rs
@@ -1,7 +1,8 @@
 // Error messages for EXXXX errors.
-// Each message should start and end with a new line, and be wrapped to 80 characters.
-// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
-register_long_diagnostics! {
+// Each message should start and end with a new line, and be wrapped to 80
+// characters.  In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use
+// `:set tw=0` to disable.
+syntax::register_diagnostics! {
 E0038: r##"
 Trait objects like `Box<Trait>` can only be constructed when certain
 requirements are satisfied by the trait in question.
@@ -39,7 +40,7 @@
 as a trait object. If the trait comes from your own crate, consider removing
 this restriction.
 
-### Method references the `Self` type in its arguments or return type
+### Method references the `Self` type in its parameters or return type
 
 This happens when a trait has a method like the following:
 
@@ -2183,11 +2184,7 @@
 static X: u32 = 42;
 ```
 "##,
-
-}
-
-
-register_diagnostics! {
+;
 //  E0006, // merged with E0005
 //  E0101, // replaced with E0282
 //  E0102, // replaced with E0282
@@ -2206,7 +2203,8 @@
 //  E0305, // expected constant
     E0311, // thing may not live long enough
     E0312, // lifetime of reference outlives lifetime of borrowed content
-    E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
+    E0313, // lifetime of borrowed pointer outlives lifetime of captured
+           // variable
     E0314, // closure outlives stack frame
     E0315, // cannot invoke closure outside of its lifetime
     E0316, // nested quantification of lifetimes
@@ -2223,12 +2221,13 @@
     E0483, // lifetime of operand does not outlive the operation
     E0484, // reference is not valid at the time of borrow
     E0485, // automatically reference is not valid at the time of borrow
-    E0486, // type of expression contains references that are not valid during...
+    E0486, // type of expression contains references that are not valid during..
     E0487, // unsafe use of destructor: destructor might be called while...
     E0488, // lifetime of variable does not enclose its declaration
     E0489, // type/lifetime parameter not in scope here
     E0490, // a value of type `..` is borrowed for too long
-    E0495, // cannot infer an appropriate lifetime due to conflicting requirements
+    E0495, // cannot infer an appropriate lifetime due to conflicting
+           // requirements
     E0566, // conflicting representation hints
     E0623, // lifetime mismatch where both parameters are anonymous regions
     E0628, // generators cannot have explicit parameters
@@ -2239,7 +2238,8 @@
     E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
     E0697, // closures cannot be static
     E0707, // multiple elided lifetimes used in arguments of `async fn`
-    E0708, // `async` non-`move` closures with parameters are not currently supported
+    E0708, // `async` non-`move` closures with parameters are not currently
+           // supported
     E0709, // multiple different lifetimes used in arguments of `async fn`
     E0710, // an unknown tool name found in scoped lint
     E0711, // a feature has been declared with conflicting stability attributes
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index eae956c..1df0942 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -4,13 +4,12 @@
 //! conflicts between multiple such attributes attached to the same
 //! item.
 
-
-use crate::ty::TyCtxt;
-use crate::ty::query::Providers;
-
 use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
+use crate::ty::TyCtxt;
+use crate::ty::query::Providers;
+
 use std::fmt::{self, Display};
 use syntax::symbol::sym;
 use syntax_pos::Span;
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index f83fbcd..f7d31ca 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -1,15 +1,17 @@
+use self::Namespace::*;
+
 use crate::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::hir;
+use crate::ty;
 use crate::util::nodemap::DefIdMap;
+
 use syntax::ast;
 use syntax::ext::base::MacroKind;
 use syntax::ast::NodeId;
 use syntax_pos::Span;
 use rustc_macros::HashStable;
-use crate::hir;
-use crate::ty;
-use std::fmt::Debug;
 
-use self::Namespace::*;
+use std::fmt::Debug;
 
 /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
@@ -115,7 +117,7 @@
         }
     }
 
-    /// An English article for the def.
+    /// Gets an English article for the definition.
     pub fn article(&self) -> &'static str {
         match *self {
             DefKind::AssocTy
@@ -134,18 +136,22 @@
     Def(DefKind, DefId),
 
     // Type namespace
+
     PrimTy(hir::PrimTy),
     SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
     ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
 
     // Value namespace
+
     SelfCtor(DefId /* impl */),  // `DefId` refers to the impl
     Local(Id),
 
     // Macro namespace
+
     NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
 
     // All namespaces
+
     Err,
 }
 
@@ -330,7 +336,7 @@
 }
 
 impl<Id> Res<Id> {
-    /// Return the `DefId` of this `Def` if it has an id, else panic.
+    /// Return the `DefId` of this `Def` if it has an ID, else panic.
     pub fn def_id(&self) -> DefId
     where
         Id: Debug,
@@ -340,7 +346,7 @@
         })
     }
 
-    /// Return `Some(..)` with the `DefId` of this `Res` if it has a id, else `None`.
+    /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.
     pub fn opt_def_id(&self) -> Option<DefId> {
         match *self {
             Res::Def(_, id) => Some(id),
@@ -379,7 +385,7 @@
         }
     }
 
-    /// An English article for the res.
+    /// Gets an English article for the `Res`.
     pub fn article(&self) -> &'static str {
         match *self {
             Res::Def(kind, _) => kind.article(),
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index c91ad78..d0bdc14 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -11,7 +11,7 @@
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum CrateNum {
-    /// A special CrateNum that we use for the tcx.rcache when decoding from
+    /// A special `CrateNum` that we use for the `tcx.rcache` when decoding from
     /// the incr. comp. cache.
     ReservedForIncrCompCache,
     Index(CrateId),
@@ -26,11 +26,10 @@
     }
 }
 
-/// Item definitions in the currently-compiled crate would have the CrateNum
-/// LOCAL_CRATE in their DefId.
+/// Item definitions in the currently-compiled crate would have the `CrateNum`
+/// `LOCAL_CRATE` in their `DefId`.
 pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0));
 
-
 impl Idx for CrateNum {
     #[inline]
     fn new(value: usize) -> Self {
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index bbde351..1f125de 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -31,11 +31,13 @@
 //! This order consistency is required in a few places in rustc, for
 //! example generator inference, and possibly also HIR borrowck.
 
-use syntax::ast::{Ident, Name, Attribute};
-use syntax_pos::Span;
+use super::itemlikevisit::DeepVisitor;
+
 use crate::hir::*;
 use crate::hir::map::Map;
-use super::itemlikevisit::DeepVisitor;
+
+use syntax::ast::{Ident, Name, Attribute};
+use syntax_pos::Span;
 
 #[derive(Copy, Clone)]
 pub enum FnKind<'a> {
@@ -139,7 +141,7 @@
 /// explicitly, you need to override each method. (And you also need
 /// to monitor future changes to `Visitor` in case a new method with a
 /// new default implementation gets introduced.)
-pub trait Visitor<'v> : Sized {
+pub trait Visitor<'v>: Sized {
     ///////////////////////////////////////////////////////////////////////////
     // Nested items.
 
@@ -162,8 +164,8 @@
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v>;
 
     /// Invoked when a nested item is encountered. By default does
-    /// nothing unless you override `nested_visit_map` to return
-    /// `Some(_)`, in which case it will walk the item. **You probably
+    /// nothing unless you override `nested_visit_map` to return other than
+    /// `None`, in which case it will walk the item. **You probably
     /// don't want to override this method** -- instead, override
     /// `nested_visit_map` or use the "shallow" or "deep" visit
     /// patterns described on `itemlikevisit::ItemLikeVisitor`. The only
@@ -201,8 +203,8 @@
 
     /// Invoked to visit the body of a function, method or closure. Like
     /// visit_nested_item, does nothing by default unless you override
-    /// `nested_visit_map` to return `Some(_)`, in which case it will walk the
-    /// body.
+    /// `nested_visit_map` to return other htan `None`, in which case it will walk
+    /// the body.
     fn visit_nested_body(&mut self, id: BodyId) {
         let opt_body = self.nested_visit_map().intra().map(|map| map.body(id));
         if let Some(body) = opt_body {
@@ -603,7 +605,7 @@
             visitor.visit_lifetime(lifetime);
             visitor.visit_ty(&mutable_type.ty)
         }
-        TyKind::Never => {},
+        TyKind::Never => {}
         TyKind::Tup(ref tuple_element_types) => {
             walk_list!(visitor, visit_ty, tuple_element_types);
         }
diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs
index 35b1812..39dd46c 100644
--- a/src/librustc/hir/itemlikevisit.rs
+++ b/src/librustc/hir/itemlikevisit.rs
@@ -1,7 +1,7 @@
 use super::{Item, ImplItem, TraitItem};
 use super::intravisit::Visitor;
 
-/// The "item-like visitor" visitor defines only the top-level methods
+/// The "item-like visitor" defines only the top-level methods
 /// that can be invoked by `Crate::visit_all_item_likes()`. Whether
 /// this trait is the right one to implement will depend on the
 /// overall pattern you need. Here are the three available patterns,
@@ -18,11 +18,11 @@
 ///    an item, but don't care about how item-like things are nested
 ///    within one another.
 ///    - Example: Examine each expression to look for its type and do some check or other.
-///    - How: Implement `intravisit::Visitor` and use
-///      `tcx.hir().krate().visit_all_item_likes(visitor.as_deep_visitor())`. Within
-///      your `intravisit::Visitor` impl, implement methods like
-///      `visit_expr()`; don't forget to invoke
-///      `intravisit::walk_visit_expr()` to keep walking the subparts.
+///    - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method
+///      to return `NestedVisitorMap::OnlyBodies` and use
+///      `tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor())`. Within
+///      your `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget
+///      to invoke `intravisit::walk_expr()` to keep walking the subparts).
 ///    - Pro: Visitor methods for any kind of HIR node, not just item-like things.
 ///    - Pro: Integrates well into dependency tracking.
 ///    - Con: Don't get information about nesting between items
@@ -30,10 +30,9 @@
 ///    item-like things.
 ///    - Example: Lifetime resolution, which wants to bring lifetimes declared on the
 ///      impl into scope while visiting the impl-items, and then back out again.
-///    - How: Implement `intravisit::Visitor` and override the
-///      `nested_visit_map()` methods to return
-///      `NestedVisitorMap::All`. Walk your crate with
-///      `intravisit::walk_crate()` invoked on `tcx.hir().krate()`.
+///    - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method
+///      to return `NestedVisitorMap::All`. Walk your crate with `intravisit::walk_crate()`
+///      invoked on `tcx.hir().krate()`.
 ///    - Pro: Visitor methods for any kind of HIR node, not just item-like things.
 ///    - Pro: Preserves nesting information
 ///    - Con: Does not integrate well into dependency tracking.
@@ -79,7 +78,7 @@
     }
 }
 
-/// A parallel variant of ItemLikeVisitor
+/// A parallel variant of `ItemLikeVisitor`.
 pub trait ParItemLikeVisitor<'hir> {
     fn visit_item(&self, item: &'hir Item);
     fn visit_trait_item(&self, trait_item: &'hir TraitItem);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 5e2aebf..48f7fc4 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -79,7 +79,7 @@
 pub struct LoweringContext<'a> {
     crate_root: Option<Symbol>,
 
-    /// Used to assign ids to HIR nodes that do not directly correspond to an AST node.
+    /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.
     sess: &'a Session,
 
     cstore: &'a dyn CrateStore,
@@ -126,7 +126,7 @@
     /// lifetime definitions in the corresponding impl or function generics.
     lifetimes_to_define: Vec<(Span, ParamName)>,
 
-    /// Whether or not in-band lifetimes are being collected. This is used to
+    /// `true` if in-band lifetimes are being collected. This is used to
     /// indicate whether or not we're in a place where new lifetimes will result
     /// in in-band lifetime definitions, such a function or an impl header,
     /// including implicit lifetimes from `impl_header_lifetime_elision`.
@@ -154,13 +154,13 @@
 }
 
 pub trait Resolver {
-    /// Obtain resolution for a `NodeId` with a single resolution.
+    /// Obtains resolution for a `NodeId` with a single resolution.
     fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;
 
-    /// Obtain per-namespace resolutions for `use` statement with the given `NoedId`.
+    /// Obtains per-namespace resolutions for `use` statement with the given `NodeId`.
     fn get_import_res(&mut self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
 
-    /// Obtain resolution for a label with the given `NodeId`.
+    /// Obtains resolution for a label with the given `NodeId`.
     fn get_label_res(&mut self, id: NodeId) -> Option<NodeId>;
 
     /// We must keep the set of definitions up to date as we add nodes that weren't in the AST.
@@ -425,19 +425,44 @@
 
         impl<'tcx, 'interner> Visitor<'tcx> for MiscCollector<'tcx, 'interner> {
             fn visit_pat(&mut self, p: &'tcx Pat) {
-                match p.node {
+                if let PatKind::Paren(..) | PatKind::Rest = p.node {
                     // Doesn't generate a HIR node
-                    PatKind::Paren(..) | PatKind::Rest => {},
-                    _ => {
-                        if let Some(owner) = self.hir_id_owner {
-                            self.lctx.lower_node_id_with_owner(p.id, owner);
-                        }
-                    }
-                };
+                } else if let Some(owner) = self.hir_id_owner {
+                    self.lctx.lower_node_id_with_owner(p.id, owner);
+                }
 
                 visit::walk_pat(self, p)
             }
 
+            // HACK(or_patterns; Centril | dlrobertson): Avoid creating
+            // HIR  nodes for `PatKind::Or` for the top level of a `ast::Arm`.
+            // This is a temporary hack that should go away once we push down
+            // `arm.pats: HirVec<P<Pat>>` -> `arm.pat: P<Pat>` to HIR. // Centril
+            fn visit_arm(&mut self, arm: &'tcx Arm) {
+                match &arm.pat.node {
+                    PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)),
+                    _ => self.visit_pat(&arm.pat),
+                }
+                walk_list!(self, visit_expr, &arm.guard);
+                self.visit_expr(&arm.body);
+                walk_list!(self, visit_attribute, &arm.attrs);
+            }
+
+            // HACK(or_patterns; Centril | dlrobertson): Same as above. // Centril
+            fn visit_expr(&mut self, e: &'tcx Expr) {
+                if let ExprKind::Let(pat, scrutinee) = &e.node {
+                    walk_list!(self, visit_attribute, e.attrs.iter());
+                    match &pat.node {
+                        PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)),
+                        _ => self.visit_pat(&pat),
+                    }
+                    self.visit_expr(scrutinee);
+                    self.visit_expr_post(e);
+                    return;
+                }
+                visit::walk_expr(self, e)
+            }
+
             fn visit_item(&mut self, item: &'tcx Item) {
                 let hir_id = self.lctx.allocate_hir_id_counter(item.id);
 
@@ -674,7 +699,7 @@
     fn lower_res(&mut self, res: Res<NodeId>) -> Res {
         res.map_id(|id| {
             self.lower_node_id_generic(id, |_| {
-                panic!("expected node_id to be lowered already for res {:#?}", res)
+                panic!("expected `NodeId` to be lowered already for res {:#?}", res);
             })
         })
     }
@@ -1291,7 +1316,7 @@
                             ImplTraitContext::Universal(in_band_ty_params),
                         );
                         // Set the name to `impl Bound1 + Bound2`.
-                        let ident = Ident::from_str(&pprust::ty_to_string(t)).with_span_pos(span);
+                        let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
                         in_band_ty_params.push(hir::GenericParam {
                             hir_id: self.lower_node_id(def_node_id),
                             name: ParamName::Plain(ident),
@@ -1339,7 +1364,7 @@
                     }
                 }
             }
-            TyKind::Mac(_) => bug!("`TyMac` should have been expanded by now."),
+            TyKind::Mac(_) => bug!("`TyMac` should have been expanded by now"),
             TyKind::CVarArgs => {
                 // Create the implicit lifetime of the "spoofed" `VaListImpl`.
                 let span = self.sess.source_map().next_point(t.span.shrink_to_lo());
@@ -2657,12 +2682,8 @@
         bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
     }
 
-    fn lower_block_with_stmts(
-        &mut self,
-        b: &Block,
-        targeted_by_break: bool,
-        mut stmts: Vec<hir::Stmt>,
-    ) -> P<hir::Block> {
+    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
+        let mut stmts = vec![];
         let mut expr = None;
 
         for (index, stmt) in b.stmts.iter().enumerate() {
@@ -2687,8 +2708,11 @@
         })
     }
 
-    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
-        self.lower_block_with_stmts(b, targeted_by_break, vec![])
+    /// Lowers a block directly to an expression, presuming that it
+    /// has no attributes and is not targeted by a `break`.
+    fn lower_block_expr(&mut self, b: &Block) -> hir::Expr {
+        let block = self.lower_block(b, false);
+        self.expr_block(block, ThinVec::new())
     }
 
     fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
@@ -2974,7 +2998,7 @@
             }
             StmtKind::Expr(ref e) => hir::StmtKind::Expr(P(self.lower_expr(e))),
             StmtKind::Semi(ref e) => hir::StmtKind::Semi(P(self.lower_expr(e))),
-            StmtKind::Mac(..) => panic!("Shouldn't exist here"),
+            StmtKind::Mac(..) => panic!("shouldn't exist here"),
         };
         smallvec![hir::Stmt {
             hir_id: self.lower_node_id(s.id),
@@ -3162,7 +3186,7 @@
 
         hir::Path {
             span,
-            res: res.map_id(|_| panic!("unexpected node_id")),
+            res: res.map_id(|_| panic!("unexpected `NodeId`")),
             segments: segments.into(),
         }
     }
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index bd21783..990728f 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -68,7 +68,7 @@
                 let ohs = P(self.lower_expr(ohs));
                 hir::ExprKind::AddrOf(m, ohs)
             }
-            ExprKind::Let(ref pats, ref scrutinee) => self.lower_expr_let(e.span, pats, scrutinee),
+            ExprKind::Let(ref pat, ref scrutinee) => self.lower_expr_let(e.span, pat, scrutinee),
             ExprKind::If(ref cond, ref then, ref else_opt) => {
                 self.lower_expr_if(e.span, cond, then, else_opt.as_deref())
             }
@@ -90,10 +90,7 @@
             ),
             ExprKind::Async(capture_clause, closure_node_id, ref block) => {
                 self.make_async_expr(capture_clause, closure_node_id, None, block.span, |this| {
-                    this.with_new_scopes(|this| {
-                        let block = this.lower_block(block, false);
-                        this.expr_block(block, ThinVec::new())
-                    })
+                    this.with_new_scopes(|this| this.lower_block_expr(block))
                 })
             }
             ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr),
@@ -227,16 +224,11 @@
         }
     }
 
-    /// Emit an error and lower `ast::ExprKind::Let(pats, scrutinee)` into:
+    /// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into:
     /// ```rust
     /// match scrutinee { pats => true, _ => false }
     /// ```
-    fn lower_expr_let(
-        &mut self,
-        span: Span,
-        pats: &[AstP<Pat>],
-        scrutinee: &Expr
-    ) -> hir::ExprKind {
+    fn lower_expr_let(&mut self, span: Span, pat: &Pat, scrutinee: &Expr) -> hir::ExprKind {
         // If we got here, the `let` expression is not allowed.
         self.sess
             .struct_span_err(span, "`let` expressions are not supported here")
@@ -246,23 +238,23 @@
 
         // For better recovery, we emit:
         // ```
-        // match scrutinee { pats => true, _ => false }
+        // match scrutinee { pat => true, _ => false }
         // ```
         // While this doesn't fully match the user's intent, it has key advantages:
         // 1. We can avoid using `abort_if_errors`.
-        // 2. We can typeck both `pats` and `scrutinee`.
-        // 3. `pats` is allowed to be refutable.
+        // 2. We can typeck both `pat` and `scrutinee`.
+        // 3. `pat` is allowed to be refutable.
         // 4. The return type of the block is `bool` which seems like what the user wanted.
         let scrutinee = self.lower_expr(scrutinee);
         let then_arm = {
-            let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
+            let pat = self.lower_pat_top_hack(pat);
             let expr = self.expr_bool(span, true);
-            self.arm(pats, P(expr))
+            self.arm(pat, P(expr))
         };
         let else_arm = {
-            let pats = hir_vec![self.pat_wild(span)];
+            let pat = self.pat_wild(span);
             let expr = self.expr_bool(span, false);
-            self.arm(pats, P(expr))
+            self.arm(hir_vec![pat], P(expr))
         };
         hir::ExprKind::Match(
             P(scrutinee),
@@ -289,15 +281,13 @@
         let else_arm = self.arm(hir_vec![else_pat], P(else_expr));
 
         // Handle then + scrutinee:
-        let then_blk = self.lower_block(then, false);
-        let then_expr = self.expr_block(then_blk, ThinVec::new());
-        let (then_pats, scrutinee, desugar) = match cond.node {
+        let then_expr = self.lower_block_expr(then);
+        let (then_pat, scrutinee, desugar) = match cond.node {
             // `<pat> => <then>`:
-            ExprKind::Let(ref pats, ref scrutinee) => {
+            ExprKind::Let(ref pat, ref scrutinee) => {
                 let scrutinee = self.lower_expr(scrutinee);
-                let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
-                let desugar = hir::MatchSource::IfLetDesugar { contains_else_clause };
-                (pats, scrutinee, desugar)
+                let pat = self.lower_pat_top_hack(pat);
+                (pat, scrutinee, hir::MatchSource::IfLetDesugar { contains_else_clause })
             }
             // `true => <then>`:
             _ => {
@@ -312,13 +302,11 @@
                 // to preserve drop semantics since `if cond { ... }` does not
                 // let temporaries live outside of `cond`.
                 let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());
-
-                let desugar = hir::MatchSource::IfDesugar { contains_else_clause };
-                let pats = hir_vec![self.pat_bool(span, true)];
-                (pats, cond, desugar)
+                let pat = self.pat_bool(span, true);
+                (hir_vec![pat], cond, hir::MatchSource::IfDesugar { contains_else_clause })
             }
         };
-        let then_arm = self.arm(then_pats, P(then_expr));
+        let then_arm = self.arm(then_pat, P(then_expr));
 
         hir::ExprKind::Match(P(scrutinee), vec![then_arm, else_arm].into(), desugar)
     }
@@ -343,10 +331,9 @@
         };
 
         // Handle then + scrutinee:
-        let then_blk = self.lower_block(body, false);
-        let then_expr = self.expr_block(then_blk, ThinVec::new());
-        let (then_pats, scrutinee, desugar, source) = match cond.node {
-            ExprKind::Let(ref pats, ref scrutinee) => {
+        let then_expr = self.lower_block_expr(body);
+        let (then_pat, scrutinee, desugar, source) = match cond.node {
+            ExprKind::Let(ref pat, ref scrutinee) => {
                 // to:
                 //
                 //   [opt_ident]: loop {
@@ -356,16 +343,15 @@
                 //     }
                 //   }
                 let scrutinee = self.with_loop_condition_scope(|t| t.lower_expr(scrutinee));
-                let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
-                let desugar = hir::MatchSource::WhileLetDesugar;
-                (pats, scrutinee, desugar, hir::LoopSource::WhileLet)
+                let pat = self.lower_pat_top_hack(pat);
+                (pat, scrutinee, hir::MatchSource::WhileLetDesugar, hir::LoopSource::WhileLet)
             }
             _ => {
                 // We desugar: `'label: while $cond $body` into:
                 //
                 // ```
                 // 'label: loop {
-                //     match DropTemps($cond) {
+                //     match drop-temps { $cond } {
                 //         true => $body,
                 //         _ => break,
                 //     }
@@ -383,14 +369,12 @@
                 // to preserve drop semantics since `while cond { ... }` does not
                 // let temporaries live outside of `cond`.
                 let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());
-
-                let desugar = hir::MatchSource::WhileDesugar;
                 // `true => <then>`:
-                let pats = hir_vec![self.pat_bool(span, true)];
-                (pats, cond, desugar, hir::LoopSource::While)
+                let pat = self.pat_bool(span, true);
+                (hir_vec![pat], cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
             }
         };
-        let then_arm = self.arm(then_pats, P(then_expr));
+        let then_arm = self.arm(then_pat, P(then_expr));
 
         // `match <scrutinee> { ... }`
         let match_expr = self.expr_match(
@@ -440,7 +424,7 @@
         hir::Arm {
             hir_id: self.next_id(),
             attrs: self.lower_attrs(&arm.attrs),
-            pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
+            pats: self.lower_pat_top_hack(&arm.pat),
             guard: match arm.guard {
                 Some(ref x) => Some(hir::Guard::If(P(self.lower_expr(x)))),
                 _ => None,
@@ -450,6 +434,16 @@
         }
     }
 
+    /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns
+    /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready
+    /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR.
+    fn lower_pat_top_hack(&mut self, pat: &Pat) -> HirVec<P<hir::Pat>> {
+        match pat.node {
+            PatKind::Or(ref ps) => ps.iter().map(|x| self.lower_pat(x)).collect(),
+            _ => hir_vec![self.lower_pat(pat)],
+        }
+    }
+
     pub(super) fn make_async_expr(
         &mut self,
         capture_clause: CaptureBy,
@@ -508,14 +502,13 @@
 
     /// Desugar `<expr>.await` into:
     /// ```rust
-    /// {
-    ///     let mut pinned = <expr>;
-    ///     loop {
+    /// match <expr> {
+    ///     mut pinned => loop {
     ///         match ::std::future::poll_with_tls_context(unsafe {
-    ///             ::std::pin::Pin::new_unchecked(&mut pinned)
+    ///             <::std::pin::Pin>::new_unchecked(&mut pinned)
     ///         }) {
     ///             ::std::task::Poll::Ready(result) => break result,
-    ///             ::std::task::Poll::Pending => {},
+    ///             ::std::task::Poll::Pending => {}
     ///         }
     ///         yield ();
     ///     }
@@ -550,21 +543,12 @@
             self.allow_gen_future.clone(),
         );
 
-        // let mut pinned = <expr>;
-        let expr = P(self.lower_expr(expr));
         let pinned_ident = Ident::with_dummy_span(sym::pinned);
         let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
             span,
             pinned_ident,
             hir::BindingAnnotation::Mutable,
         );
-        let pinned_let = self.stmt_let_pat(
-            ThinVec::new(),
-            span,
-            Some(expr),
-            pinned_pat,
-            hir::LocalSource::AwaitDesugar,
-        );
 
         // ::std::future::poll_with_tls_context(unsafe {
         //     ::std::pin::Pin::new_unchecked(&mut pinned)
@@ -622,7 +606,7 @@
             self.arm(hir_vec![pending_pat], empty_block)
         };
 
-        let match_stmt = {
+        let inner_match_stmt = {
             let match_expr = self.expr_match(
                 span,
                 poll_expr,
@@ -644,10 +628,11 @@
 
         let loop_block = P(self.block_all(
             span,
-            hir_vec![match_stmt, yield_stmt],
+            hir_vec![inner_match_stmt, yield_stmt],
             None,
         ));
 
+        // loop { .. }
         let loop_expr = P(hir::Expr {
             hir_id: loop_hir_id,
             node: hir::ExprKind::Loop(
@@ -659,10 +644,14 @@
             attrs: ThinVec::new(),
         });
 
-        hir::ExprKind::Block(
-            P(self.block_all(span, hir_vec![pinned_let], Some(loop_expr))),
-            None,
-        )
+        // mut pinned => loop { ... }
+        let pinned_arm = self.arm(hir_vec![pinned_pat], loop_expr);
+
+        // match <expr> {
+        //     mut pinned => loop { .. }
+        // }
+        let expr = P(self.lower_expr(expr));
+        hir::ExprKind::Match(expr, hir_vec![pinned_arm], hir::MatchSource::AwaitDesugar)
     }
 
     fn lower_expr_closure(
@@ -1255,7 +1244,6 @@
                 ThinVec::from(attrs.clone()),
             ));
             let ok_pat = self.pat_ok(span, val_pat);
-
             self.arm(hir_vec![ok_pat], val_expr)
         };
 
@@ -1317,7 +1305,7 @@
     /// `{ let _t = $expr; _t }` but should provide better compile-time performance.
     ///
     /// The drop order can be important in e.g. `if expr { .. }`.
-    fn expr_drop_temps(
+    pub(super) fn expr_drop_temps(
         &mut self,
         span: Span,
         expr: P<hir::Expr>,
@@ -1486,7 +1474,10 @@
         }
     }
 
-    fn arm(&mut self, pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
+    /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns
+    /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready
+    /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR.
+    fn arm(&mut self, pats: HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
         hir::Arm {
             hir_id: self.next_id(),
             attrs: hir_vec![],
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 4e432f4..61be40a 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -718,7 +718,7 @@
                         AnonymousLifetimeMode::PassThrough,
                         |this, _| {
                             (
-                                // Disallow impl Trait in foreign items
+                                // Disallow `impl Trait` in foreign items.
                                 this.lower_fn_decl(fdec, None, false, None),
                                 this.lower_fn_params_to_names(fdec),
                             )
@@ -732,7 +732,7 @@
                         self.lower_ty(t, ImplTraitContext::disallowed()), self.lower_mutability(m))
                 }
                 ForeignItemKind::Ty => hir::ForeignItemKind::Type,
-                ForeignItemKind::Macro(_) => panic!("shouldn't exist here"),
+                ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"),
             },
             vis: self.lower_visibility(&i.vis, None),
             span: i.span,
@@ -1071,10 +1071,7 @@
     }
 
     fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
-        self.lower_fn_body(decl, |this| {
-            let body = this.lower_block(body, false);
-            this.expr_block(body, ThinVec::new())
-        })
+        self.lower_fn_body(decl, |this| this.lower_block_expr(body))
     }
 
     pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
@@ -1102,8 +1099,7 @@
             // from:
             //
             //     async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
-            //       async move {
-            //       }
+            //         <body>
             //     }
             //
             // into:
@@ -1116,11 +1112,19 @@
             //         let <pattern> = __arg1;
             //         let __arg0 = __arg0;
             //         let <pattern> = __arg0;
+            //         drop-temps { <body> } // see comments later in fn for details
             //       }
             //     }
             //
             // If `<pattern>` is a simple ident, then it is lowered to a single
             // `let <pattern> = <pattern>;` statement as an optimization.
+            //
+            // Note that the body is embedded in `drop-temps`; an
+            // equivalent desugaring would be `return { <body>
+            // };`. The key point is that we wish to drop all the
+            // let-bound variables and temporaries created in the body
+            // (and its tail expression!) before we drop the
+            // parameters (c.f. rust-lang/rust#64512).
             for (index, parameter) in decl.inputs.iter().enumerate() {
                 let parameter = this.lower_param(parameter);
                 let span = parameter.pat.span;
@@ -1219,8 +1223,36 @@
             let async_expr = this.make_async_expr(
                 CaptureBy::Value, closure_id, None, body.span,
                 |this| {
-                    let body = this.lower_block_with_stmts(body, false, statements);
-                    this.expr_block(body, ThinVec::new())
+                    // Create a block from the user's function body:
+                    let user_body = this.lower_block_expr(body);
+
+                    // Transform into `drop-temps { <user-body> }`, an expression:
+                    let desugared_span = this.mark_span_with_reason(
+                        DesugaringKind::Async,
+                        user_body.span,
+                        None,
+                    );
+                    let user_body = this.expr_drop_temps(
+                        desugared_span,
+                        P(user_body),
+                        ThinVec::new(),
+                    );
+
+                    // As noted above, create the final block like
+                    //
+                    // ```
+                    // {
+                    //   let $param_pattern = $raw_param;
+                    //   ...
+                    //   drop-temps { <user-body> }
+                    // }
+                    // ```
+                    let body = this.block_all(
+                        desugared_span,
+                        statements.into(),
+                        Some(P(user_body)),
+                    );
+                    this.expr_block(P(body), ThinVec::new())
                 });
             (HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new()))
         })
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 773bb8d..4179cf2 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -186,7 +186,7 @@
             });
 
         let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| {
-            let name = cstore.crate_name_untracked(cnum).as_str();
+            let name = cstore.crate_name_untracked(cnum).as_interned_str();
             let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
             let hash = cstore.crate_hash_untracked(cnum);
             (name, disambiguator, hash)
@@ -340,7 +340,7 @@
     /// their outer items.
 
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
-        panic!("visit_nested_xxx must be manually implemented in this visitor")
+        panic!("`visit_nested_xxx` must be manually implemented in this visitor");
     }
 
     fn visit_nested_item(&mut self, item: ItemId) {
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 17bcb1d..d1cc7a8 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -31,7 +31,7 @@
         self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span)
     }
 
-    pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
+    fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
         let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def);
         f(self);
         self.parent_def = orig_parent_def;
@@ -74,6 +74,22 @@
         })
     }
 
+    fn collect_field(&mut self, field: &'a StructField, index: Option<usize>) {
+        if field.is_placeholder {
+            self.visit_macro_invoc(field.id);
+        } else {
+            let name = field.ident.map(|ident| ident.name)
+                .or_else(|| index.map(sym::integer))
+                .unwrap_or_else(|| {
+                    let node_id = NodeId::placeholder_from_expn_id(self.expansion);
+                    sym::integer(self.definitions.placeholder_field_indices[&node_id])
+                })
+                .as_interned_str();
+            let def = self.create_def(field.id, DefPathData::ValueNs(name), field.span);
+            self.with_parent(def, |this| visit::walk_struct_field(this, field));
+        }
+    }
+
     pub fn visit_macro_invoc(&mut self, id: NodeId) {
         self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def);
     }
@@ -155,6 +171,9 @@
     }
 
     fn visit_variant(&mut self, v: &'a Variant) {
+        if v.is_placeholder {
+            return self.visit_macro_invoc(v.id);
+        }
         let def = self.create_def(v.id,
                                   DefPathData::TypeNs(v.ident.as_interned_str()),
                                   v.span);
@@ -167,17 +186,22 @@
     }
 
     fn visit_variant_data(&mut self, data: &'a VariantData) {
+        // The assumption here is that non-`cfg` macro expansion cannot change field indices.
+        // It currently holds because only inert attributes are accepted on fields,
+        // and every such attribute expands into a single field after it's resolved.
         for (index, field) in data.fields().iter().enumerate() {
-            let name = field.ident.map(|ident| ident.name)
-                .unwrap_or_else(|| sym::integer(index));
-            let def = self.create_def(field.id,
-                                      DefPathData::ValueNs(name.as_interned_str()),
-                                      field.span);
-            self.with_parent(def, |this| this.visit_struct_field(field));
+            self.collect_field(field, Some(index));
+            if field.is_placeholder && field.ident.is_none() {
+                self.definitions.placeholder_field_indices.insert(field.id, index);
+            }
         }
     }
 
     fn visit_generic_param(&mut self, param: &'a GenericParam) {
+        if param.is_placeholder {
+            self.visit_macro_invoc(param.id);
+            return;
+        }
         let name = param.ident.as_interned_str();
         let def_path_data = match param.kind {
             GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name),
@@ -294,4 +318,42 @@
             }
         }
     }
+
+    fn visit_arm(&mut self, arm: &'a Arm) {
+        if arm.is_placeholder {
+            self.visit_macro_invoc(arm.id)
+        } else {
+            visit::walk_arm(self, arm)
+        }
+    }
+
+    fn visit_field(&mut self, f: &'a Field) {
+        if f.is_placeholder {
+            self.visit_macro_invoc(f.id)
+        } else {
+            visit::walk_field(self, f)
+        }
+    }
+
+    fn visit_field_pattern(&mut self, fp: &'a FieldPat) {
+        if fp.is_placeholder {
+            self.visit_macro_invoc(fp.id)
+        } else {
+            visit::walk_field_pattern(self, fp)
+        }
+    }
+
+    fn visit_param(&mut self, p: &'a Param) {
+        if p.is_placeholder {
+            self.visit_macro_invoc(p.id)
+        } else {
+            visit::walk_param(self, p)
+        }
+    }
+
+    // This method is called only when we are visiting an individual field
+    // after expanding an attribute on it.
+    fn visit_struct_field(&mut self, field: &'a StructField) {
+        self.collect_field(field, None);
+    }
 }
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 6dc3c70..187bc59 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -7,10 +7,12 @@
 use crate::hir;
 use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, CRATE_DEF_INDEX};
 use crate::ich::Fingerprint;
+use crate::session::CrateDisambiguator;
+use crate::util::nodemap::NodeMap;
+
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::{IndexVec};
 use rustc_data_structures::stable_hasher::StableHasher;
-use crate::session::CrateDisambiguator;
 use std::borrow::Borrow;
 use std::fmt::Write;
 use std::hash::Hash;
@@ -18,12 +20,11 @@
 use syntax::ext::hygiene::ExpnId;
 use syntax::symbol::{Symbol, sym, InternedString};
 use syntax_pos::{Span, DUMMY_SP};
-use crate::util::nodemap::NodeMap;
 
-/// The DefPathTable maps DefIndexes to DefKeys and vice versa.
-/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
-/// stores the DefIndex of its parent.
-/// There is one DefPathTable for each crate.
+/// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
+/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
+/// stores the `DefIndex` of its parent.
+/// There is one `DefPathTable` for each crate.
 #[derive(Clone, Default, RustcDecodable, RustcEncodable)]
 pub struct DefPathTable {
     index_to_key: Vec<DefKey>,
@@ -103,6 +104,8 @@
     /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
     /// we know what parent node that fragment should be attached to thanks to this table.
     invocation_parents: FxHashMap<ExpnId, DefIndex>,
+    /// Indices of unnamed struct or variant fields with unresolved attributes.
+    pub(super) placeholder_field_indices: NodeMap<usize>,
 }
 
 /// A unique identifier that we can use to lookup a definition
@@ -121,7 +124,7 @@
     fn compute_stable_hash(&self, parent_hash: DefPathHash) -> DefPathHash {
         let mut hasher = StableHasher::new();
 
-        // We hash a 0u8 here to disambiguate between regular DefPath hashes,
+        // We hash a `0u8` here to disambiguate between regular `DefPath` hashes,
         // and the special "root_parent" below.
         0u8.hash(&mut hasher);
         parent_hash.hash(&mut hasher);
@@ -145,8 +148,7 @@
                                crate_disambiguator: CrateDisambiguator)
                                -> DefPathHash {
         let mut hasher = StableHasher::new();
-        // Disambiguate this from a regular DefPath hash,
-        // see compute_stable_hash() above.
+        // Disambiguate this from a regular `DefPath` hash; see `compute_stable_hash()` above.
         1u8.hash(&mut hasher);
         crate_name.hash(&mut hasher);
         crate_disambiguator.hash(&mut hasher);
@@ -155,10 +157,10 @@
 }
 
 /// A pair of `DefPathData` and an integer disambiguator. The integer is
-/// normally 0, but in the event that there are multiple defs with the
+/// normally `0`, but in the event that there are multiple defs with the
 /// same `parent` and `data`, we use this field to disambiguate
 /// between them. This introduces some artificial ordering dependency
-/// but means that if you have (e.g.) two impls for the same type in
+/// but means that if you have, e.g., two impls for the same type in
 /// the same module, they do get distinct `DefId`s.
 #[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)]
 pub struct DisambiguatedDefPathData {
@@ -277,29 +279,34 @@
 pub enum DefPathData {
     // Root: these should only be used for the root nodes, because
     // they are treated specially by the `def_path` function.
-    /// The crate root (marker)
+
+    /// The crate root (marker).
     CrateRoot,
-    // Catch-all for random DefId things like `DUMMY_NODE_ID`
+    // Catch-all for random `DefId` things like `DUMMY_NODE_ID`.
     Misc,
+
     // Different kinds of items and item-like things:
-    /// An impl
+
+    /// An impl.
     Impl,
-    /// Something in the type NS
+    /// Something in the type namespace.
     TypeNs(InternedString),
-    /// Something in the value NS
+    /// Something in the value namespace.
     ValueNs(InternedString),
-    /// Something in the macro NS
+    /// Something in the macro namespace.
     MacroNs(InternedString),
-    /// Something in the lifetime NS
+    /// Something in the lifetime namespace.
     LifetimeNs(InternedString),
-    /// A closure expression
+    /// A closure expression.
     ClosureExpr,
-    // Subportions of items
-    /// Implicit ctor for a unit or tuple-like struct or enum variant.
+
+    // Subportions of items:
+
+    /// Implicit constructor for a unit or tuple-like struct or enum variant.
     Ctor,
-    /// A constant expression (see {ast,hir}::AnonConst).
+    /// A constant expression (see `{ast,hir}::AnonConst`).
     AnonConst,
-    /// An `impl Trait` type node
+    /// An `impl Trait` type node.
     ImplTrait,
     /// Identifies a piece of crate metadata that is global to a whole crate
     /// (as opposed to just one item). `GlobalMetaData` components are only
@@ -435,7 +442,7 @@
         self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index);
         self.set_invocation_parent(ExpnId::root(), root_index);
 
-        // Allocate some other DefIndices that always must exist.
+        // Allocate some other `DefIndex`es that always must exist.
         GlobalMetaDataKind::allocate_def_indices(self);
 
         root_index
@@ -458,7 +465,7 @@
                 data,
                 self.table.def_key(self.node_to_def_index[&node_id]));
 
-        // The root node must be created with create_root_def()
+        // The root node must be created with `create_root_def()`.
         assert!(data != DefPathData::CrateRoot);
 
         // Find the next free disambiguator for this key.
@@ -486,9 +493,9 @@
         assert_eq!(index.index(), self.def_index_to_node.len());
         self.def_index_to_node.push(node_id);
 
-        // Some things for which we allocate DefIndices don't correspond to
-        // anything in the AST, so they don't have a NodeId. For these cases
-        // we don't need a mapping from NodeId to DefIndex.
+        // Some things for which we allocate `DefIndex`es don't correspond to
+        // anything in the AST, so they don't have a `NodeId`. For these cases
+        // we don't need a mapping from `NodeId` to `DefIndex`.
         if node_id != ast::DUMMY_NODE_ID {
             debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
             self.node_to_def_index.insert(node_id, index);
@@ -498,7 +505,7 @@
             self.expansions_that_defined.insert(index, expn_id);
         }
 
-        // The span is added if it isn't dummy
+        // The span is added if it isn't dummy.
         if !span.is_dummy() {
             self.def_index_to_span.insert(index, span);
         }
@@ -506,12 +513,12 @@
         index
     }
 
-    /// Initialize the `ast::NodeId` to `HirId` mapping once it has been generated during
+    /// Initializes the `ast::NodeId` to `HirId` mapping once it has been generated during
     /// AST to HIR lowering.
     pub fn init_node_id_to_hir_id_mapping(&mut self,
                                           mapping: IndexVec<ast::NodeId, hir::HirId>) {
         assert!(self.node_to_hir_id.is_empty(),
-                "Trying initialize NodeId -> HirId mapping twice");
+                "trying to initialize `NodeId` -> `HirId` mapping twice");
         self.node_to_hir_id = mapping;
     }
 
@@ -533,7 +540,7 @@
 
     pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: DefIndex) {
         let old_parent = self.invocation_parents.insert(invoc_id, parent);
-        assert!(old_parent.is_none(), "parent def-index is reset for an invocation");
+        assert!(old_parent.is_none(), "parent `DefIndex` is reset for an invocation");
     }
 }
 
@@ -585,9 +592,9 @@
     }
 }
 
-// We define the GlobalMetaDataKind enum with this macro because we want to
+// We define the `GlobalMetaDataKind` enum with this macro because we want to
 // make sure that we exhaustively iterate over all variants when registering
-// the corresponding DefIndices in the DefTable.
+// the corresponding `DefIndex`es in the `DefTable`.
 macro_rules! define_global_metadata_kind {
     (pub enum GlobalMetaDataKind {
         $($variant:ident),*
@@ -609,7 +616,7 @@
                         DUMMY_SP
                     );
 
-                    // Make sure calling def_index does not crash.
+                    // Make sure calling `def_index` does not crash.
                     instance.def_index(&definitions.table);
                 })*
             }
@@ -623,7 +630,7 @@
                     }
                 };
 
-                // These DefKeys are all right after the root,
+                // These `DefKey`s are all right after the root,
                 // so a linear search is fine.
                 let index = def_path_table.index_to_key
                                           .iter()
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index eb8be6e..5cec8a5 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -5,10 +5,15 @@
 };
 
 use crate::dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex};
-
+use crate::hir::*;
+use crate::hir::DefKind;
 use crate::hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId};
-
+use crate::hir::itemlikevisit::ItemLikeVisitor;
+use crate::hir::print::Nested;
 use crate::middle::cstore::CrateStoreDyn;
+use crate::ty::query::Providers;
+use crate::util::nodemap::FxHashMap;
+use crate::util::common::time;
 
 use rustc_target::spec::abi::Abi;
 use rustc_data_structures::svh::Svh;
@@ -18,15 +23,7 @@
 use syntax::ext::base::MacroKind;
 use syntax_pos::{Span, DUMMY_SP};
 
-use crate::hir::*;
-use crate::hir::DefKind;
-use crate::hir::itemlikevisit::ItemLikeVisitor;
-use crate::hir::print::Nested;
-use crate::util::nodemap::FxHashMap;
-use crate::util::common::time;
-
 use std::result::Result::Err;
-use crate::ty::query::Providers;
 
 pub mod blocks;
 mod collector;
@@ -627,7 +624,7 @@
             .unwrap_or(hir_id)
     }
 
-    /// Check if the node is an argument. An argument is a local variable whose
+    /// Checks if the node is an argument. An argument is a local variable whose
     /// immediate parent is an item or a closure.
     pub fn is_argument(&self, id: HirId) -> bool {
         match self.find(id) {
@@ -733,7 +730,7 @@
     /// ```
     /// fn foo(x: usize) -> bool {
     ///     if x == 1 {
-    ///         true  // `get_return_block` gets passed the `id` corresponding
+    ///         true  // If `get_return_block` gets passed the `id` corresponding
     ///     } else {  // to this, it will return `foo`'s `HirId`.
     ///         false
     ///     }
@@ -743,7 +740,7 @@
     /// ```
     /// fn foo(x: usize) -> bool {
     ///     loop {
-    ///         true  // `get_return_block` gets passed the `id` corresponding
+    ///         true  // If `get_return_block` gets passed the `id` corresponding
     ///     }         // to this, it will return `None`.
     ///     false
     /// }
@@ -994,9 +991,9 @@
         self.map.iter().enumerate().filter_map(|(i, local_map)| {
             local_map.as_ref().map(|m| (i, m))
         }).flat_map(move |(array_index, local_map)| {
-            // Iterate over each valid entry in the local map
+            // Iterate over each valid entry in the local map.
             local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| {
-                // Reconstruct the HirId based on the 3 indices we used to find it
+                // Reconstruct the `HirId` based on the 3 indices we used to find it.
                 HirId {
                     owner: DefIndex::from(array_index),
                     local_id: i,
@@ -1207,7 +1204,7 @@
         definitions,
     };
 
-    time(sess, "validate hir map", || {
+    time(sess, "validate HIR map", || {
         hir_id_validator::check_crate(&map);
     });
 
@@ -1247,9 +1244,9 @@
             Node::Pat(a)          => self.print_pat(&a),
             Node::Arm(a)          => self.print_arm(&a),
             Node::Block(a)        => {
-                // containing cbox, will be closed by print-block at }
+                // Containing cbox, will be closed by print-block at `}`.
                 self.cbox(print::INDENT_UNIT);
-                // head-ibox, will be closed by print-block after {
+                // Head-ibox, will be closed by print-block after `{`.
                 self.ibox(0);
                 self.print_block(&a)
             }
@@ -1257,8 +1254,8 @@
             Node::Visibility(a)   => self.print_visibility(&a),
             Node::GenericParam(_) => bug!("cannot print Node::GenericParam"),
             Node::Field(_)        => bug!("cannot print StructField"),
-            // these cases do not carry enough information in the
-            // hir_map to reconstruct their full structure for pretty
+            // These cases do not carry enough information in the
+            // `hir_map` to reconstruct their full structure for pretty
             // printing.
             Node::Ctor(..)        => bug!("cannot print isolated Ctor"),
             Node::Local(a)        => self.print_local_decl(&a),
@@ -1273,8 +1270,8 @@
     let id_str = if include_id { &id_str[..] } else { "" };
 
     let path_str = || {
-        // This functionality is used for debugging, try to use TyCtxt to get
-        // the user-friendly path, otherwise fall back to stringifying DefPath.
+        // This functionality is used for debugging, try to use `TyCtxt` to get
+        // the user-friendly path, otherwise fall back to stringifying `DefPath`.
         crate::ty::tls::with_opt(|tcx| {
             if let Some(tcx) = tcx {
                 let def_id = map.local_def_id(id);
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index d2c45a5..2c8590a 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -13,26 +13,24 @@
 use crate::hir::def::{Res, DefKind};
 use crate::hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
 use crate::hir::ptr::P;
-use crate::util::nodemap::{NodeMap, FxHashSet};
 use crate::mir::mono::Linkage;
+use crate::ty::AdtKind;
+use crate::ty::query::Providers;
+use crate::util::nodemap::{NodeMap, FxHashSet};
 
 use errors::FatalError;
 use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan};
 use syntax::source_map::Spanned;
-use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
 use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
 use syntax::attr::{InlineAttr, OptimizeAttr};
 use syntax::symbol::{Symbol, kw};
 use syntax::tokenstream::TokenStream;
 use syntax::util::parser::ExprPrecedence;
-use crate::ty::AdtKind;
-use crate::ty::query::Providers;
-
+use rustc_target::spec::abi::Abi;
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_macros::HashStable;
-
 use rustc_serialize::{self, Encoder, Encodable, Decoder, Decodable};
 use std::collections::{BTreeSet, BTreeMap};
 use std::fmt;
@@ -99,7 +97,8 @@
         } = *self;
 
         owner.encode(s)?;
-        local_id.encode(s)
+        local_id.encode(s)?;
+        Ok(())
     }
 }
 
@@ -121,7 +120,7 @@
     }
 }
 
-// Hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module
+// Hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module.
 mod item_local_id_inner {
     use rustc_data_structures::indexed_vec::Idx;
     use rustc_macros::HashStable;
@@ -191,7 +190,7 @@
     Fresh(usize),
 
     /// Indicates an illegal name was given and an error has been
-    /// repored (so we should squelch other derived errors). Occurs
+    /// reported (so we should squelch other derived errors). Occurs
     /// when, e.g., `'_` is used in the wrong place.
     Error,
 }
@@ -746,7 +745,7 @@
     // Attributes from non-exported macros, kept only for collecting the library feature list.
     pub non_exported_macro_attrs: HirVec<Attribute>,
 
-    // N.B., we use a BTreeMap here so that `visit_all_items` iterates
+    // N.B., we use a `BTreeMap` here so that `visit_all_items` iterates
     // over the ids in increasing order. In principle it should not
     // matter what order we visit things in, but in *practice* it
     // does, because it can affect the order in which errors are
@@ -1403,13 +1402,13 @@
     pub body: BodyId,
 }
 
-/// An expression
+/// An expression.
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Expr {
-    pub span: Span,
+    pub hir_id: HirId,
     pub node: ExprKind,
     pub attrs: ThinVec<Attribute>,
-    pub hir_id: HirId,
+    pub span: Span,
 }
 
 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -2422,37 +2421,37 @@
     ///
     /// or just
     ///
-    /// `use foo::bar::baz;` (with `as baz` implicitly on the right)
+    /// `use foo::bar::baz;` (with `as baz` implicitly on the right).
     Use(P<Path>, UseKind),
 
-    /// A `static` item
+    /// A `static` item.
     Static(P<Ty>, Mutability, BodyId),
-    /// A `const` item
+    /// A `const` item.
     Const(P<Ty>, BodyId),
-    /// A function declaration
+    /// A function declaration.
     Fn(P<FnDecl>, FnHeader, Generics, BodyId),
-    /// A module
+    /// A module.
     Mod(Mod),
-    /// An external module
+    /// An external module.
     ForeignMod(ForeignMod),
-    /// Module-level inline assembly (from global_asm!)
+    /// Module-level inline assembly (from `global_asm!`).
     GlobalAsm(P<GlobalAsm>),
-    /// A type alias, e.g., `type Foo = Bar<u8>`
+    /// A type alias, e.g., `type Foo = Bar<u8>`.
     TyAlias(P<Ty>, Generics),
-    /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`
+    /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
     OpaqueTy(OpaqueTy),
-    /// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`
+    /// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
     Enum(EnumDef, Generics),
-    /// A struct definition, e.g., `struct Foo<A> {x: A}`
+    /// A struct definition, e.g., `struct Foo<A> {x: A}`.
     Struct(VariantData, Generics),
-    /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`
+    /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
     Union(VariantData, Generics),
-    /// A trait definition
+    /// A trait definition.
     Trait(IsAuto, Unsafety, Generics, GenericBounds, HirVec<TraitItemRef>),
-    /// A trait alias
+    /// A trait alias.
     TraitAlias(Generics, GenericBounds),
 
-    /// An implementation, eg `impl<A> Trait for Foo { .. }`
+    /// An implementation, e.g., `impl<A> Trait for Foo { .. }`.
     Impl(Unsafety,
          ImplPolarity,
          Defaultness,
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 21cc72e..cfbfb5e 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1293,11 +1293,11 @@
                 self.print_closure_params(&decl, body);
                 self.s.space();
 
-                // this is a bare expression
+                // This is a bare expression.
                 self.ann.nested(self, Nested::Body(body));
                 self.end(); // need to close a box
 
-                // a box will be closed by print_expr, but we didn't want an overall
+                // A box will be closed by `print_expr`, but we didn't want an overall
                 // wrapper so we closed the corresponding opening. so create an
                 // empty box to satisfy the close.
                 self.ibox(0);
@@ -1307,9 +1307,9 @@
                     self.print_ident(label.ident);
                     self.word_space(":");
                 }
-                // containing cbox, will be closed by print-block at }
+                // containing cbox, will be closed by print-block at `}`
                 self.cbox(INDENT_UNIT);
-                // head-box, will be closed by print-block after {
+                // head-box, will be closed by print-block after `{`
                 self.ibox(0);
                 self.print_block(&blk);
             }
@@ -1759,7 +1759,7 @@
                         self.word_space(",");
                     }
                     if let PatKind::Wild = p.node {
-                        // Print nothing
+                        // Print nothing.
                     } else {
                         self.print_pat(&p);
                     }
@@ -1891,7 +1891,7 @@
             i += 1;
 
             if let hir::TyKind::Infer = ty.node {
-                // Print nothing
+                // Print nothing.
             } else {
                 s.s.word(":");
                 s.s.space();
@@ -2221,7 +2221,6 @@
     }
 }
 
-// Dup'ed from parse::classify, but adapted for the HIR.
 /// Does this expression require a semicolon to be treated
 /// as a statement? The negation of this: 'can this expression
 /// be used as a statement without a semicolon' -- is used
@@ -2229,6 +2228,8 @@
 ///     if true {...} else {...}
 ///      |x| 5
 /// isn't parsed as (if true {...} else {...} | x) | 5
+//
+// Duplicated from `parse::classify`, but adapted for the HIR.
 fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool {
     match e.node {
         hir::ExprKind::Match(..) |
@@ -2238,7 +2239,7 @@
     }
 }
 
-/// this statement requires a semicolon after it.
+/// This statement requires a semicolon after it.
 /// note that in one case (stmt_semi), we've already
 /// seen the semicolon, and thus don't need another.
 fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool {
@@ -2277,7 +2278,7 @@
     }
 }
 
-/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any
+/// Expressions that syntactically contain an "exterior" struct literal, i.e., not surrounded by any
 /// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
 /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
 fn contains_exterior_struct_lit(value: &hir::Expr) -> bool {
@@ -2287,7 +2288,7 @@
         hir::ExprKind::Assign(ref lhs, ref rhs) |
         hir::ExprKind::AssignOp(_, ref lhs, ref rhs) |
         hir::ExprKind::Binary(_, ref lhs, ref rhs) => {
-            // X { y: 1 } + X { y: 2 }
+            // `X { y: 1 } + X { y: 2 }`
             contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs)
         }
         hir::ExprKind::Unary(_, ref x) |
@@ -2295,12 +2296,12 @@
         hir::ExprKind::Type(ref x, _) |
         hir::ExprKind::Field(ref x, _) |
         hir::ExprKind::Index(ref x, _) => {
-            // &X { y: 1 }, X { y: 1 }.y
+            // `&X { y: 1 }, X { y: 1 }.y`
             contains_exterior_struct_lit(&x)
         }
 
         hir::ExprKind::MethodCall(.., ref exprs) => {
-            // X { y: 1 }.bar(...)
+            // `X { y: 1 }.bar(...)`
             contains_exterior_struct_lit(&exprs[0])
         }
 
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index e77faea..182a9ad 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -12,7 +12,6 @@
 use std::cell::RefCell;
 
 use syntax::ast;
-
 use syntax::source_map::SourceMap;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::symbol::Symbol;
@@ -20,9 +19,9 @@
 use syntax_pos::{Span, DUMMY_SP};
 use syntax_pos::hygiene;
 
-use rustc_data_structures::stable_hasher::{HashStable,
-                                           StableHasher, StableHasherResult,
-                                           ToStableHashKey};
+use rustc_data_structures::stable_hasher::{
+    HashStable, StableHasher, StableHasherResult, ToStableHashKey,
+};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use smallvec::SmallVec;
 
@@ -32,9 +31,9 @@
 }
 
 /// This is the context state available during incr. comp. hashing. It contains
-/// enough information to transform DefIds and HirIds into stable DefPaths (i.e.
-/// a reference to the TyCtxt) and it holds a few caches for speeding up various
-/// things (e.g., each DefId/DefPath is only hashed once).
+/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e.,
+/// a reference to the `TyCtxt`) and it holds a few caches for speeding up various
+/// things (e.g., each `DefId`/`DefPath` is only hashed once).
 #[derive(Clone)]
 pub struct StableHashingContext<'a> {
     sess: &'a Session,
@@ -46,7 +45,7 @@
     node_id_hashing_mode: NodeIdHashingMode,
 
     // Very often, we are hashing something that does not need the
-    // CachingSourceMapView, so we initialize it lazily.
+    // `CachingSourceMapView`, so we initialize it lazily.
     raw_source_map: &'a SourceMap,
     caching_source_map: Option<CachingSourceMapView<'a>>,
 }
@@ -57,24 +56,24 @@
     HashDefPath,
 }
 
-/// The BodyResolver allows to map a BodyId to the corresponding hir::Body.
-/// We could also just store a plain reference to the hir::Crate but we want
+/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`.
+/// We could also just store a plain reference to the `hir::Crate` but we want
 /// to avoid that the crate is used to get untracked access to all of the HIR.
 #[derive(Clone, Copy)]
 struct BodyResolver<'tcx>(&'tcx hir::Crate);
 
 impl<'tcx> BodyResolver<'tcx> {
-    // Return a reference to the hir::Body with the given BodyId.
-    // DOES NOT DO ANY TRACKING, use carefully.
+    /// Returns a reference to the `hir::Body` with the given `BodyId`.
+    /// **Does not do any tracking**; use carefully.
     fn body(self, id: hir::BodyId) -> &'tcx hir::Body {
         self.0.body(id)
     }
 }
 
 impl<'a> StableHashingContext<'a> {
-    // The `krate` here is only used for mapping BodyIds to Bodies.
-    // Don't use it for anything else or you'll run the risk of
-    // leaking data out of the tracking system.
+    /// The `krate` here is only used for mapping `BodyId`s to `Body`s.
+    /// Don't use it for anything else or you'll run the risk of
+    /// leaking data out of the tracking system.
     #[inline]
     pub fn new(sess: &'a Session,
                krate: &'a hir::Crate,
@@ -217,9 +216,7 @@
     }
 }
 
-impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {
-}
-
+impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {}
 
 impl<'a> HashStable<StableHashingContext<'a>> for hir::BodyId {
     fn hash_stable<W: StableHasherResult>(&self,
@@ -292,16 +289,15 @@
 }
 
 impl<'a> HashStable<StableHashingContext<'a>> for Span {
-
-    // Hash a span in a stable way. We can't directly hash the span's BytePos
-    // fields (that would be similar to hashing pointers, since those are just
-    // offsets into the SourceMap). Instead, we hash the (file name, line, column)
-    // triple, which stays the same even if the containing SourceFile has moved
-    // within the SourceMap.
-    // Also note that we are hashing byte offsets for the column, not unicode
-    // codepoint offsets. For the purpose of the hash that's sufficient.
-    // Also, hashing filenames is expensive so we avoid doing it twice when the
-    // span starts and ends in the same file, which is almost always the case.
+    /// Hashes a span in a stable way. We can't directly hash the span's `BytePos`
+    /// fields (that would be similar to hashing pointers, since those are just
+    /// offsets into the `SourceMap`). Instead, we hash the (file name, line, column)
+    /// triple, which stays the same even if the containing `SourceFile` has moved
+    /// within the `SourceMap`.
+    /// Also note that we are hashing byte offsets for the column, not unicode
+    /// codepoint offsets. For the purpose of the hash that's sufficient.
+    /// Also, hashing filenames is expensive so we avoid doing it twice when the
+    /// span starts and ends in the same file, which is almost always the case.
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
@@ -340,7 +336,7 @@
         }
 
         std_hash::Hash::hash(&TAG_VALID_SPAN, hasher);
-        // We truncate the stable_id hash and line and col numbers. The chances
+        // We truncate the stable ID hash and line and column numbers. The chances
         // of causing a collision this way should be minimal.
         std_hash::Hash::hash(&(file_lo.name_hash as u64), hasher);
 
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index fb981d9..6e6492d 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -5,8 +5,10 @@
 use crate::hir::map::DefPathHash;
 use crate::hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX};
 use crate::ich::{StableHashingContext, NodeIdHashingMode, Fingerprint};
-use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
-                                           StableHasher, StableHasherResult};
+
+use rustc_data_structures::stable_hasher::{
+    HashStable, ToStableHashKey, StableHasher, StableHasherResult,
+};
 use smallvec::SmallVec;
 use std::mem;
 use syntax::ast;
@@ -82,9 +84,9 @@
     }
 }
 
-// The following implementations of HashStable for ItemId, TraitItemId, and
-// ImplItemId deserve special attention. Normally we do not hash NodeIds within
-// the HIR, since they just signify a HIR nodes own path. But ItemId et al
+// The following implementations of HashStable for `ItemId`, `TraitItemId`, and
+// `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within
+// the HIR, since they just signify a HIR nodes own path. But `ItemId` et al
 // are used when another item in the HIR is *referenced* and we certainly
 // want to pick up on a reference changing its target, so we hash the NodeIds
 // in "DefPath Mode".
@@ -131,7 +133,6 @@
     }
 }
 
-
 impl_stable_hash_for!(struct ast::Label {
     ident
 });
@@ -241,7 +242,7 @@
     }
 }
 
-impl_stable_hash_for!(enum ::syntax::ast::CrateSugar {
+impl_stable_hash_for!(enum ast::CrateSugar {
     JustCrate,
     PubCrate,
 });
@@ -365,8 +366,7 @@
     }
 }
 
-impl<'a> ToStableHashKey<StableHashingContext<'a>>
-for hir::def_id::DefIndex {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::def_id::DefIndex {
     type KeyType = DefPathHash;
 
     #[inline]
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 05e2c78..a33181e 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -9,7 +9,7 @@
 use syntax::ast;
 use syntax::feature_gate;
 use syntax::parse::token;
-use syntax::symbol::{InternedString, LocalInternedString};
+use syntax::symbol::InternedString;
 use syntax::tokenstream;
 use syntax_pos::SourceFile;
 
@@ -39,27 +39,6 @@
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
-    #[inline]
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        let s: &str = &**self;
-        s.hash_stable(hcx, hasher);
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
-    type KeyType = LocalInternedString;
-
-    #[inline]
-    fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'a>)
-                          -> LocalInternedString {
-        self.clone()
-    }
-}
-
 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
@@ -136,9 +115,10 @@
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
-            ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
+            ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue, ref is_soft } => {
                 reason.hash_stable(hcx, hasher);
                 issue.hash_stable(hcx, hasher);
+                is_soft.hash_stable(hcx, hasher);
             }
             ::syntax::attr::StabilityLevel::Stable { ref since } => {
                 since.hash_stable(hcx, hasher);
@@ -411,9 +391,17 @@
 impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
     Root,
     Macro(kind, descr),
+    AstPass(kind),
     Desugaring(kind)
 });
 
+impl_stable_hash_for!(enum ::syntax_pos::hygiene::AstPass {
+    StdImports,
+    TestHarness,
+    ProcMacroHarness,
+    PluginMacroDefs,
+});
+
 impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind {
     CondTemporary,
     Async,
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 0ddc921..f230c53 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -168,25 +168,21 @@
     }
 }
 
-// Allocations treat their relocations specially
-impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::Allocation {
+// `Relocations` with default type parameters is a sorted map.
+impl<'a, Tag> HashStable<StableHashingContext<'a>>
+for mir::interpret::Relocations<Tag>
+where
+    Tag: HashStable<StableHashingContext<'a>>,
+{
     fn hash_stable<W: StableHasherResult>(
         &self,
         hcx: &mut StableHashingContext<'a>,
         hasher: &mut StableHasher<W>,
     ) {
-        let mir::interpret::Allocation {
-            bytes, relocations, undef_mask, align, mutability,
-            extra: _,
-        } = self;
-        bytes.hash_stable(hcx, hasher);
-        relocations.len().hash_stable(hcx, hasher);
-        for reloc in relocations.iter() {
+        self.len().hash_stable(hcx, hasher);
+        for reloc in self.iter() {
             reloc.hash_stable(hcx, hasher);
         }
-        undef_mask.hash_stable(hcx, hasher);
-        align.hash_stable(hcx, hasher);
-        mutability.hash_stable(hcx, hasher);
     }
 }
 
@@ -208,7 +204,7 @@
     fn hash_stable<W: StableHasherResult>(&self,
                                           _hcx: &mut StableHashingContext<'a>,
                                           _hasher: &mut StableHasher<W>) {
-        // TyVid values are confined to an inference context and hence
+        // `TyVid` values are confined to an inference context and hence
         // should not be hashed.
         bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self)
     }
@@ -218,7 +214,7 @@
     fn hash_stable<W: StableHasherResult>(&self,
                                           _hcx: &mut StableHashingContext<'a>,
                                           _hasher: &mut StableHasher<W>) {
-        // IntVid values are confined to an inference context and hence
+        // `IntVid` values are confined to an inference context and hence
         // should not be hashed.
         bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self)
     }
@@ -228,7 +224,7 @@
     fn hash_stable<W: StableHasherResult>(&self,
                                           _hcx: &mut StableHashingContext<'a>,
                                           _hasher: &mut StableHasher<W>) {
-        // FloatVid values are confined to an inference context and hence
+        // `FloatVid` values are confined to an inference context and hence
         // should not be hashed.
         bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self)
     }
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 5dfa0d2..96d40bc 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -97,7 +97,7 @@
                self.tag(),
                a,
                b);
-        let origin = Subtype(self.fields.trace.clone());
+        let origin = Subtype(box self.fields.trace.clone());
         self.fields.infcx.borrow_region_constraints()
                          .make_eqregion(origin, a, b);
         Ok(a)
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 9be73cf..ab24b3f 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -55,7 +55,8 @@
 use crate::hir::Node;
 use crate::infer::opaque_types;
 use crate::middle::region;
-use crate::traits::{ObligationCause, ObligationCauseCode};
+use crate::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
+use crate::traits::{ObligationCauseCode};
 use crate::ty::error::TypeError;
 use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
@@ -624,13 +625,13 @@
                     }
                 }
             }
-            ObligationCauseCode::MatchExpressionArm {
+            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
                 source,
                 ref prior_arms,
                 last_ty,
                 discrim_hir_id,
                 ..
-            } => match source {
+            }) => match source {
                 hir::MatchSource::IfLetDesugar { .. } => {
                     let msg = "`if let` arms have incompatible types";
                     err.span_label(cause.span, msg);
@@ -681,7 +682,7 @@
                     }
                 }
             },
-            ObligationCauseCode::IfExpression { then, outer, semicolon } => {
+            ObligationCauseCode::IfExpression(box IfExpressionCause { then, outer, semicolon }) => {
                 err.span_label(then, "expected because of this");
                 outer.map(|sp| err.span_label(sp, "if and else have incompatible types"));
                 if let Some(sp) = semicolon {
@@ -1136,12 +1137,19 @@
         if let Some((expected, found)) = expected_found {
             match (terr, is_simple_error, expected == found) {
                 (&TypeError::Sorts(ref values), false, true) => {
+                    let sort_string = | a_type: Ty<'tcx> |
+                        if let ty::Opaque(def_id, _) = a_type.sty {
+                            format!(" (opaque type at {})", self.tcx.sess.source_map()
+                                .mk_substr_filename(self.tcx.def_span(def_id)))
+                        } else {
+                            format!(" ({})", a_type.sort_string(self.tcx))
+                        };
                     diag.note_expected_found_extra(
                         &"type",
                         expected,
                         found,
-                        &format!(" ({})", values.expected.sort_string(self.tcx)),
-                        &format!(" ({})", values.found.sort_string(self.tcx)),
+                        &sort_string(values.expected),
+                        &sort_string(values.found),
                     );
                 }
                 (_, false, _) => {
@@ -1615,19 +1623,21 @@
         use crate::traits::ObligationCauseCode::*;
         match self.code {
             CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
-            MatchExpressionArm { source, .. } => Error0308(match source {
-                hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have incompatible types",
-                hir::MatchSource::TryDesugar => {
-                    "try expression alternatives have incompatible types"
-                }
-                _ => "match arms have incompatible types",
-            }),
+            MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =>
+                Error0308(match source {
+                    hir::MatchSource::IfLetDesugar { .. } =>
+                        "`if let` arms have incompatible types",
+                    hir::MatchSource::TryDesugar => {
+                        "try expression alternatives have incompatible types"
+                    }
+                    _ => "match arms have incompatible types",
+                }),
             IfExpression { .. } => Error0308("if and else have incompatible types"),
             IfExpressionWithNoElse => Error0317("if may be missing an else clause"),
             MainFunctionType => Error0580("main function has wrong type"),
             StartFunctionType => Error0308("start function has wrong type"),
             IntrinsicType => Error0308("intrinsic has wrong type"),
-            MethodReceiver => Error0308("mismatched method receiver"),
+            MethodReceiver => Error0308("mismatched `self` parameter type"),
 
             // In the case where we have no more specific thing to
             // say, also take a look at the error code, maybe we can
@@ -1636,6 +1646,9 @@
                 TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
                     Error0644("closure/generator type that references itself")
                 }
+                TypeError::IntrinsicCast => {
+                    Error0308("cannot coerce intrinsics to function pointers")
+                }
                 _ => Error0308("mismatched types"),
             },
         }
@@ -1646,7 +1659,7 @@
         match self.code {
             CompareImplMethodObligation { .. } => "method type is compatible with trait",
             ExprAssignable => "expression is assignable",
-            MatchExpressionArm { source, .. } => match source {
+            MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source {
                 hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types",
                 _ => "match arms have compatible types",
             },
diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
index b4fb018..bfa8353 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -30,7 +30,7 @@
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -50,7 +50,7 @@
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -70,7 +70,7 @@
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -92,7 +92,7 @@
                 _,
                 _,
                 _,
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -108,7 +108,7 @@
             )),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -125,7 +125,7 @@
             )),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -142,7 +142,7 @@
             )),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(TypeTrace {
+                SubregionOrigin::Subtype(box TypeTrace {
                     cause,
                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                 }),
@@ -192,23 +192,28 @@
             vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
         );
 
-        let mut err = self.tcx().sess.struct_span_err(
-            cause.span(self.tcx()),
-            &format!(
-                "implementation of `{}` is not general enough",
-                self.tcx().def_path_str(trait_def_id),
-            ),
+        let span = cause.span(self.tcx());
+        let msg = format!(
+            "implementation of `{}` is not general enough",
+            self.tcx().def_path_str(trait_def_id),
+        );
+        let mut err = self.tcx().sess.struct_span_err(span, &msg);
+        err.span_label(
+            self.tcx().def_span(trait_def_id),
+            format!("trait `{}` defined here", self.tcx().def_path_str(trait_def_id)),
         );
 
-        match cause.code {
-            ObligationCauseCode::ItemObligation(def_id) => {
-                err.note(&format!(
-                    "Due to a where-clause on `{}`,",
-                    self.tcx().def_path_str(def_id),
-                ));
-            }
-            _ => (),
-        }
+        let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code {
+            err.span_label(span, "doesn't satisfy where-clause");
+            err.span_label(
+                self.tcx().def_span(def_id),
+                &format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)),
+            );
+            true
+        } else {
+            err.span_label(span, &msg);
+            false
+        };
 
         let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
             def_id: trait_def_id,
@@ -295,6 +300,7 @@
             expected_has_vid,
             actual_has_vid,
             any_self_ty_has_vid,
+            leading_ellipsis,
         );
 
         err
@@ -318,6 +324,7 @@
         expected_has_vid: Option<usize>,
         actual_has_vid: Option<usize>,
         any_self_ty_has_vid: bool,
+        leading_ellipsis: bool,
     ) {
         // HACK(eddyb) maybe move this in a more central location.
         #[derive(Copy, Clone)]
@@ -392,13 +399,15 @@
 
             let mut note = if passive_voice {
                 format!(
-                    "`{}` would have to be implemented for the type `{}`",
+                    "{}`{}` would have to be implemented for the type `{}`",
+                    if leading_ellipsis { "..." } else { "" },
                     expected_trait_ref,
                     expected_trait_ref.map(|tr| tr.self_ty()),
                 )
             } else {
                 format!(
-                    "`{}` must implement `{}`",
+                    "{}`{}` must implement `{}`",
+                    if leading_ellipsis { "..." } else { "" },
                     expected_trait_ref.map(|tr| tr.self_ty()),
                     expected_trait_ref,
                 )
@@ -407,20 +416,20 @@
             match (has_sub, has_sup) {
                 (Some(n1), Some(n2)) => {
                     let _ = write!(note,
-                        ", for any two lifetimes `'{}` and `'{}`",
+                        ", for any two lifetimes `'{}` and `'{}`...",
                         std::cmp::min(n1, n2),
                         std::cmp::max(n1, n2),
                     );
                 }
                 (Some(n), _) | (_, Some(n)) => {
                     let _ = write!(note,
-                        ", for any lifetime `'{}`",
+                        ", for any lifetime `'{}`...",
                         n,
                     );
                 }
                 (None, None) => if let Some(n) = expected_has_vid {
                     let _ = write!(note,
-                        ", for some specific lifetime `'{}`",
+                        ", for some specific lifetime `'{}`...",
                         n,
                     );
                 },
@@ -439,13 +448,13 @@
 
             let mut note = if passive_voice {
                 format!(
-                    "but `{}` is actually implemented for the type `{}`",
+                    "...but `{}` is actually implemented for the type `{}`",
                     actual_trait_ref,
                     actual_trait_ref.map(|tr| tr.self_ty()),
                 )
             } else {
                 format!(
-                    "but `{}` actually implements `{}`",
+                    "...but `{}` actually implements `{}`",
                     actual_trait_ref.map(|tr| tr.self_ty()),
                     actual_trait_ref,
                 )
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index caed428..115ffea 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -138,7 +138,7 @@
                                           sup: Region<'tcx>)
                                           -> DiagnosticBuilder<'tcx> {
         match origin {
-            infer::Subtype(trace) => {
+            infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
                 let mut err = self.report_and_explain_type_error(trace, &terr);
                 self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "...");
@@ -450,7 +450,7 @@
     ) -> DiagnosticBuilder<'tcx> {
         // I can't think how to do better than this right now. -nikomatsakis
         match placeholder_origin {
-            infer::Subtype(trace) => {
+            infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsPlaceholderMismatch;
                 self.report_and_explain_type_error(trace, &terr)
             }
diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs
index 2cef521..10e4532 100644
--- a/src/librustc/infer/glb.rs
+++ b/src/librustc/infer/glb.rs
@@ -57,7 +57,7 @@
                a,
                b);
 
-        let origin = Subtype(self.fields.trace.clone());
+        let origin = Subtype(box self.fields.trace.clone());
         Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b))
     }
 
diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs
index e20372f..8b64cda 100644
--- a/src/librustc/infer/lub.rs
+++ b/src/librustc/infer/lub.rs
@@ -57,7 +57,7 @@
                a,
                b);
 
-        let origin = Subtype(self.fields.trace.clone());
+        let origin = Subtype(box self.fields.trace.clone());
         Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b))
     }
 
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index cc28567e..a886c44 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -254,7 +254,7 @@
 #[derive(Clone, Debug)]
 pub enum SubregionOrigin<'tcx> {
     /// Arose from a subtyping relation
-    Subtype(TypeTrace<'tcx>),
+    Subtype(Box<TypeTrace<'tcx>>),
 
     /// Stack-allocated closures cannot outlive innermost loop
     /// or function so as to ensure we only require finite stack
@@ -340,6 +340,10 @@
     },
 }
 
+// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(SubregionOrigin<'_>, 32);
+
 /// Places that type/region parameters can appear.
 #[derive(Clone, Copy, Debug)]
 pub enum ParameterOrigin {
@@ -1321,13 +1325,13 @@
         T: TypeFoldable<'tcx>,
     {
         if !value.needs_infer() {
-            return value.clone(); // avoid duplicated subst-folding
+            return value.clone(); // Avoid duplicated subst-folding.
         }
         let mut r = resolve::OpportunisticVarResolver::new(self);
         value.fold_with(&mut r)
     }
 
-    /// Returns first unresolved variable contained in `T`. In the
+    /// Returns the first unresolved variable contained in `T`. In the
     /// process of visiting `T`, this will resolve (where possible)
     /// type variables in `T`, but it never constructs the final,
     /// resolved type, so it's more efficient than
@@ -1462,7 +1466,7 @@
 
         let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
 
-        // this can get called from typeck (by euv), and moves_by_default
+        // This can get called from typeck (by euv), and `moves_by_default`
         // rightly refuses to work with inference variables, but
         // moves_by_default has a cache, which we want to use in other
         // cases.
@@ -1482,7 +1486,7 @@
         closure_kind_ty.to_opt_closure_kind()
     }
 
-    /// Obtain the signature of a closure. For closures, unlike
+    /// Obtains the signature of a closure. For closures, unlike
     /// `tcx.fn_sig(def_id)`, this method will work during the
     /// type-checking of the enclosing function and return the closure
     /// signature in its partially inferred state.
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index cd1d206..76db55e 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -130,7 +130,7 @@
         // FIXME -- we have more fine-grained information available
         // from the "cause" field, we could perhaps give more tailored
         // error messages.
-        let origin = SubregionOrigin::Subtype(self.fields.trace.clone());
+        let origin = SubregionOrigin::Subtype(box self.fields.trace.clone());
         self.fields.infcx.borrow_region_constraints()
                          .make_subregion(origin, a, b);
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 368f5bb..7a01ae6 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -45,7 +45,6 @@
 #![feature(non_exhaustive)]
 #![feature(optin_builtin_traits)]
 #![feature(range_is_empty)]
-#![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(specialization)]
 #![feature(unboxed_closures)]
@@ -68,7 +67,6 @@
 
 #[macro_use] extern crate bitflags;
 extern crate getopts;
-#[macro_use] extern crate lazy_static;
 #[macro_use] extern crate scoped_tls;
 #[cfg(windows)]
 extern crate libc;
@@ -88,8 +86,6 @@
 #[macro_use]
 mod macros;
 
-// N.B., this module needs to be declared first so diagnostics are
-// registered before they are used.
 pub mod error_codes;
 
 #[macro_use]
@@ -97,7 +93,6 @@
 
 #[macro_use]
 pub mod arena;
-pub mod cfg;
 pub mod dep_graph;
 pub mod hir;
 pub mod ich;
@@ -143,6 +138,3 @@
 
 // Allows macros to refer to this crate as `::rustc`
 extern crate self as rustc;
-
-// Build the diagnostics array at the end so that the metadata includes error use sites.
-__build_diagnostic_array! { librustc, DIAGNOSTICS }
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 6d9a6bb..dd29057 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -395,6 +395,12 @@
     "reservation of a two-phased borrow conflicts with other shared borrows"
 }
 
+declare_lint! {
+    pub SOFT_UNSTABLE,
+    Deny,
+    "a feature gate that doesn't break dependent crates"
+}
+
 declare_lint_pass! {
     /// Does nothing as a lint pass, but registers some `Lint`s
     /// that are used by other parts of the compiler.
@@ -460,6 +466,7 @@
         NESTED_IMPL_TRAIT,
         MUTABLE_BORROW_RESERVATION_CONFLICT,
         INDIRECT_STRUCTURAL_MATCH,
+        SOFT_UNSTABLE,
     ]
 }
 
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index affda25..c658120 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -16,32 +16,32 @@
 
 use self::TargetLint::*;
 
-use std::slice;
-use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter};
+use crate::hir;
+use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use crate::hir::intravisit as hir_visit;
+use crate::hir::intravisit::Visitor;
+use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
 use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject};
 use crate::lint::{LintArray, Level, Lint, LintId, LintPass, LintBuffer};
 use crate::lint::builtin::BuiltinLintDiagnostics;
 use crate::lint::levels::{LintLevelSets, LintLevelsBuilder};
 use crate::middle::privacy::AccessLevels;
-use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
 use crate::session::{config, early_error, Session};
 use crate::ty::{self, print::Printer, subst::Kind, TyCtxt, Ty};
 use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
 use crate::util::nodemap::FxHashMap;
 use crate::util::common::time;
 
+use errors::DiagnosticBuilder;
+use std::slice;
 use std::default::Default as StdDefault;
+use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter};
+use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
 use syntax::ast;
 use syntax::edition;
-use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}};
-use errors::DiagnosticBuilder;
-use crate::hir;
-use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use crate::hir::intravisit as hir_visit;
-use crate::hir::intravisit::Visitor;
-use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit as ast_visit;
+use syntax_pos::{MultiSpan, Span, symbol::Symbol};
 
 /// Information about the registered lints.
 ///
@@ -405,7 +405,7 @@
     pub fn check_lint_name(
         &self,
         lint_name: &str,
-        tool_name: Option<LocalInternedString>,
+        tool_name: Option<Symbol>,
     ) -> CheckLintNameResult<'_> {
         let complete_name = if let Some(tool_name) = tool_name {
             format!("{}::{}", tool_name, lint_name)
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 139f434..cbc6dbd 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -291,7 +291,7 @@
                         continue;
                     }
 
-                    Some(tool_ident.as_str())
+                    Some(tool_ident.name)
                 } else {
                     None
                 };
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index a3518b2..5b490b7 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -646,6 +646,30 @@
         (Level::Forbid, None) => sess.struct_err(msg),
     };
 
+    // Check for future incompatibility lints and issue a stronger warning.
+    let lints = sess.lint_store.borrow();
+    let lint_id = LintId::of(lint);
+    let future_incompatible = lints.future_incompatible(lint_id);
+
+    // If this code originates in a foreign macro, aka something that this crate
+    // did not itself author, then it's likely that there's nothing this crate
+    // can do about it. We probably want to skip the lint entirely.
+    if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
+        // Any suggestions made here are likely to be incorrect, so anything we
+        // emit shouldn't be automatically fixed by rustfix.
+        err.allow_suggestions(false);
+
+        // If this is a future incompatible lint it'll become a hard error, so
+        // we have to emit *something*. Also allow lints to whitelist themselves
+        // on a case-by-case basis for emission in a foreign macro.
+        if future_incompatible.is_none() && !lint.report_in_external_macro {
+            err.cancel();
+            // Don't continue further, since we don't want to have
+            // `diag_span_note_once` called for a diagnostic that isn't emitted.
+            return err;
+        }
+    }
+
     let name = lint.name_lower();
     match src {
         LintSource::Default => {
@@ -695,10 +719,6 @@
 
     err.code(DiagnosticId::Lint(name));
 
-    // Check for future incompatibility lints and issue a stronger warning.
-    let lints = sess.lint_store.borrow();
-    let lint_id = LintId::of(lint);
-    let future_incompatible = lints.future_incompatible(lint_id);
     if let Some(future_incompatible) = future_incompatible {
         const STANDARD_MESSAGE: &str =
             "this was previously accepted by the compiler but is being phased out; \
@@ -723,22 +743,6 @@
         err.note(&citation);
     }
 
-    // If this code originates in a foreign macro, aka something that this crate
-    // did not itself author, then it's likely that there's nothing this crate
-    // can do about it. We probably want to skip the lint entirely.
-    if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
-        // Any suggestions made here are likely to be incorrect, so anything we
-        // emit shouldn't be automatically fixed by rustfix.
-        err.allow_suggestions(false);
-
-        // If this is a future incompatible lint it'll become a hard error, so
-        // we have to emit *something*. Also allow lints to whitelist themselves
-        // on a case-by-case basis for emission in a foreign macro.
-        if future_incompatible.is_none() && !lint.report_in_external_macro {
-            err.cancel()
-        }
-    }
-
     return err
 }
 
@@ -868,15 +872,15 @@
     let expn_data = span.ctxt().outer_expn_data();
     match expn_data.kind {
         ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
-        ExpnKind::Desugaring(_) => true, // well, it's "external"
+        ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
         ExpnKind::Macro(MacroKind::Bang, _) => {
             if expn_data.def_site.is_dummy() {
-                // dummy span for the def_site means it's an external macro
+                // Dummy span for the `def_site` means it's an external macro.
                 return true;
             }
             match sess.source_map().span_to_snippet(expn_data.def_site) {
                 Ok(code) => !code.starts_with("macro_rules"),
-                // no snippet = external macro or compiler-builtin expansion
+                // No snippet means external macro or compiler-builtin expansion.
                 Err(_) => true,
             }
         }
@@ -884,7 +888,7 @@
     }
 }
 
-/// Returns whether `span` originates in a derive macro's expansion
+/// Returns `true` if `span` originates in a derive-macro's expansion.
 pub fn in_derive_expansion(span: Span) -> bool {
     if let ExpnKind::Macro(MacroKind::Derive, _) = span.ctxt().outer_expn_data().kind {
         return true;
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 53c099c..ba27d33 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -16,17 +16,17 @@
 
     map: &'a hir_map::Map<'tcx>,
 
-    // The top-level function called 'main'
+    /// The top-level function called `main`.
     main_fn: Option<(HirId, Span)>,
 
-    // The function that has attribute named 'main'
+    /// The function that has attribute named `main`.
     attr_main_fn: Option<(HirId, Span)>,
 
-    // The function that has the attribute 'start' on it
+    /// The function that has the attribute 'start' on it.
     start_fn: Option<(HirId, Span)>,
 
-    // The functions that one might think are 'main' but aren't, e.g.
-    // main functions not defined at the top level. For diagnostics.
+    /// The functions that one might think are `main` but aren't, e.g.
+    /// main functions not defined at the top level. For diagnostics.
     non_main_fns: Vec<(HirId, Span)> ,
 }
 
@@ -39,11 +39,11 @@
     }
 
     fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem) {
-        // entry fn is never a trait item
+        // Entry fn is never a trait item.
     }
 
     fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) {
-        // entry fn is never an impl item
+        // Entry fn is never a trait item.
     }
 }
 
@@ -54,7 +54,7 @@
         *ty == config::CrateType::Executable
     });
     if !any_exe {
-        // No need to find a main function
+        // No need to find a main function.
         return None;
     }
 
@@ -88,7 +88,7 @@
                 EntryPointType::MainAttr
             } else if item.ident.name == sym::main {
                 if at_root {
-                    // This is a top-level function so can be 'main'.
+                    // This is a top-level function so can be `main`.
                     EntryPointType::MainNamed
                 } else {
                     EntryPointType::OtherMain
@@ -109,7 +109,7 @@
                 ctxt.main_fn = Some((item.hir_id, item.span));
             } else {
                 span_err!(ctxt.session, item.span, E0136,
-                          "multiple 'main' functions");
+                          "multiple `main` functions");
             }
         },
         EntryPointType::OtherMain => {
@@ -130,7 +130,7 @@
             if ctxt.start_fn.is_none() {
                 ctxt.start_fn = Some((item.hir_id, item.span));
             } else {
-                struct_span_err!(ctxt.session, item.span, E0138, "multiple 'start' functions")
+                struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions")
                     .span_label(ctxt.start_fn.unwrap().1, "previous `start` function here")
                     .span_label(item.span, "multiple `start` functions")
                     .emit();
@@ -148,34 +148,48 @@
     } else if let Some((hir_id, _)) = visitor.main_fn {
         Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main))
     } else {
-        // No main function
-        let mut err = struct_err!(tcx.sess, E0601,
-            "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
-        if !visitor.non_main_fns.is_empty() {
-            // There were some functions named 'main' though. Try to give the user a hint.
-            err.note("the main function must be defined at the crate level \
-                      but you have one or more functions named 'main' that are not \
-                      defined at the crate level. Either move the definition or \
-                      attach the `#[main]` attribute to override this behavior.");
-            for &(_, span) in &visitor.non_main_fns {
-                err.span_note(span, "here is a function named 'main'");
-            }
-            err.emit();
-        } else {
-            if let Some(ref filename) = tcx.sess.local_crate_source_file {
-                err.note(&format!("consider adding a `main` function to `{}`", filename.display()));
-            }
-            if tcx.sess.teach(&err.get_code().unwrap()) {
-                err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
-                          to get started: https://doc.rust-lang.org/book/");
-            }
-            err.emit();
-        }
-
+        no_main_err(tcx, visitor);
         None
     }
 }
 
+fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
+    // There is no main function.
+    let mut err = struct_err!(tcx.sess, E0601,
+        "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
+    let filename = &tcx.sess.local_crate_source_file;
+    let note = if !visitor.non_main_fns.is_empty() {
+        for &(_, span) in &visitor.non_main_fns {
+            err.span_note(span, "here is a function named `main`");
+        }
+        err.note("you have one or more functions named `main` not defined at the crate level");
+        err.help("either move the `main` function definitions or attach the `#[main]` attribute \
+                  to one of them");
+        // There were some functions named `main` though. Try to give the user a hint.
+        format!("the main function must be defined at the crate level{}",
+                 filename.as_ref().map(|f| format!(" (in `{}`)", f.display())).unwrap_or_default())
+    } else if let Some(filename) = filename {
+        format!("consider adding a `main` function to `{}`", filename.display())
+    } else {
+        String::from("consider adding a `main` function at the crate level")
+    };
+    let sp = tcx.hir().krate().span;
+    // The file may be empty, which leads to the diagnostic machinery not emitting this
+    // note. This is a relatively simple way to detect that case and emit a span-less
+    // note instead.
+    if let Ok(_) = tcx.sess.source_map().lookup_line(sp.lo()) {
+        err.set_span(sp);
+        err.span_label(sp, &note);
+    } else {
+        err.note(&note);
+    }
+    if tcx.sess.teach(&err.get_code().unwrap()) {
+        err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
+                  to get started: https://doc.rust-lang.org/book/");
+    }
+    err.emit();
+}
+
 pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> {
     tcx.entry_fn(LOCAL_CRATE)
 }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 222c2a4..de6dada 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -596,7 +596,7 @@
             }
 
             hir::StmtKind::Item(_) => {
-                // we don't visit nested items in this visitor,
+                // We don't visit nested items in this visitor,
                 // only the fn body we were given.
             }
 
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 6b04600..c5d9a72 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -3,10 +3,8 @@
 //! Language items are items that represent concepts intrinsic to the language
 //! itself. Examples are:
 //!
-//! * Traits that specify "kinds"; e.g., "Sync", "Send".
-//!
-//! * Traits that represent operators; e.g., "Add", "Sub", "Index".
-//!
+//! * Traits that specify "kinds"; e.g., `Sync`, `Send`.
+//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
 //! * Functions called by the compiler itself.
 
 pub use self::LangItem::*;
@@ -151,11 +149,11 @@
     }
 
     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
-        // at present, lang items are always items, not trait items
+        // At present, lang items are always items, not trait items.
     }
 
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
-        // at present, lang items are always items, not impl items
+        // At present, lang items are always items, not impl items.
     }
 }
 
@@ -204,7 +202,7 @@
     }
 }
 
-/// Extract the first `lang = "$name"` out of a list of attributes.
+/// Extracts the first `lang = "$name"` out of a list of attributes.
 /// The attributes `#[panic_handler]` and `#[alloc_error_handler]`
 /// are also extracted out when found.
 pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
@@ -216,7 +214,7 @@
     }))
 }
 
-/// Traverse and collect all the lang items in all crates.
+/// Traverses and collects all the lang items in all crates.
 pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems {
     // Initialize the collector.
     let mut collector = LanguageItemCollector::new(tcx);
@@ -246,6 +244,7 @@
 
 language_item_table! {
 //  Variant name,                Name,                 Method name,             Target;
+    BoolImplItem,                "bool",               bool_impl,               Target::Impl;
     CharImplItem,                "char",               char_impl,               Target::Impl;
     StrImplItem,                 "str",                str_impl,                Target::Impl;
     SliceImplItem,               "slice",              slice_impl,              Target::Impl;
@@ -367,7 +366,7 @@
 
     MaybeUninitLangItem,         "maybe_uninit",       maybe_uninit,            Target::Union;
 
-    // Align offset for stride != 1, must not panic.
+    // Align offset for stride != 1; must not panic.
     AlignOffsetLangItem,         "align_offset",       align_offset_fn,         Target::Fn;
 
     TerminationTraitLangItem,    "termination",        termination,             Target::Trait;
@@ -378,7 +377,7 @@
 
 impl<'tcx> TyCtxt<'tcx> {
     /// Returns the `DefId` for a given `LangItem`.
-    /// If not found, fatally abort compilation.
+    /// If not found, fatally aborts compilation.
     pub fn require_lang_item(&self, lang_item: LangItem, span: Option<Span>) -> DefId {
         self.lang_items().require(lang_item).unwrap_or_else(|msg| {
             if let Some(span) = span {
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 28aa86e..b9d8a4e 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -6,29 +6,27 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
 
-use crate::ich::{StableHashingContext, NodeIdHashingMode};
-use crate::util::nodemap::{FxHashMap, FxHashSet};
-use crate::ty;
-
-use std::mem;
-use std::fmt;
-use rustc_macros::HashStable;
-use syntax::source_map;
-use syntax_pos::{Span, DUMMY_SP};
-use crate::ty::{DefIdTree, TyCtxt};
-use crate::ty::query::Providers;
-
 use crate::hir;
 use crate::hir::Node;
 use crate::hir::def_id::DefId;
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use crate::hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
-use rustc_data_structures::indexed_vec::Idx;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use crate::ich::{StableHashingContext, NodeIdHashingMode};
+use crate::util::nodemap::{FxHashMap, FxHashSet};
+use crate::ty::{self, DefIdTree, TyCtxt};
+use crate::ty::query::Providers;
 
-/// Scope represents a statically-describable scope that can be
-/// used to bound the lifetime/region for values.
+use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+use rustc_macros::HashStable;
+use syntax::source_map;
+use syntax_pos::{Span, DUMMY_SP};
+
+use std::fmt;
+use std::mem;
+
+/// Represents a statically-describable scope that can be used to
+/// bound the lifetime/region for values.
 ///
 /// `Node(node_id)`: Any AST node that has any scope at all has the
 /// `Node(node_id)` scope. Other variants represent special cases not
@@ -225,7 +223,7 @@
     /// have lifetime parameters free in this body.
     root_parent: Option<hir::HirId>,
 
-    /// `parent_map` maps from a scope ID to the enclosing scope id;
+    /// Maps from a scope ID to the enclosing scope id;
     /// this is usually corresponding to the lexical nesting, though
     /// in the case of closures the parent scope is the innermost
     /// conditional expression or repeating block. (Note that the
@@ -233,17 +231,17 @@
     /// the closure itself.)
     parent_map: FxHashMap<Scope, (Scope, ScopeDepth)>,
 
-    /// `var_map` maps from a variable or binding ID to the block in
-    /// which that variable is declared.
+    /// Maps from a variable or binding ID to the block in which that
+    /// variable is declared.
     var_map: FxHashMap<hir::ItemLocalId, Scope>,
 
-    /// maps from a `NodeId` to the associated destruction scope (if any)
+    /// Maps from a `NodeId` to the associated destruction scope (if any).
     destruction_scopes: FxHashMap<hir::ItemLocalId, Scope>,
 
-    /// `rvalue_scopes` includes entries for those expressions whose cleanup scope is
-    /// larger than the default. The map goes from the expression id
-    /// to the cleanup scope id. For rvalues not present in this
-    /// table, the appropriate cleanup scope is the innermost
+    /// `rvalue_scopes` includes entries for those expressions whose
+    /// cleanup scope is larger than the default. The map goes from the
+    /// expression ID to the cleanup scope id. For rvalues not present in
+    /// this table, the appropriate cleanup scope is the innermost
     /// enclosing statement, conditional expression, or repeating
     /// block (see `terminating_scopes`).
     /// In constants, None is used to indicate that certain expressions
@@ -318,7 +316,7 @@
     ///     4. By `2.` and `3.`, `D` is *statically* storage-dead at `U`,
     ///     QED.
     ///
-    /// I don't think this property relies on `3.` in an essential way - it
+    /// This property ought to not on (3) in an essential way -- it
     /// is probably still correct even if we have "unrestricted" terminating
     /// scopes. However, why use the complicated proof when a simple one
     /// works?
@@ -341,20 +339,20 @@
 
 #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub struct YieldData {
-    /// `Span` of the yield.
+    /// The `Span` of the yield.
     pub span: Span,
-    /// The number of expressions and patterns appearing before the `yield` in the body + 1.
+    /// The number of expressions and patterns appearing before the `yield` in the body plus one.
     pub expr_and_pat_count: usize,
     pub source: hir::YieldSource,
 }
 
 #[derive(Debug, Copy, Clone)]
 pub struct Context {
-    /// the root of the current region tree. This is typically the id
+    /// The root of the current region tree. This is typically the id
     /// of the innermost fn body. Each fn forms its own disjoint tree
     /// in the region hierarchy. These fn bodies are themselves
     /// arranged into a tree. See the "Modeling closures" section of
-    /// the README in infer::region_constraints for more
+    /// the README in `infer::region_constraints` for more
     /// details.
     root_id: Option<hir::ItemLocalId>,
 
@@ -369,15 +367,15 @@
 struct RegionResolutionVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
 
-    // The number of expressions and patterns visited in the current body
+    // The number of expressions and patterns visited in the current body.
     expr_and_pat_count: usize,
     // When this is `true`, we record the `Scopes` we encounter
     // when processing a Yield expression. This allows us to fix
     // up their indices.
     pessimistic_yield: bool,
-    // Stores scopes when pessimistic_yield is true.
+    // Stores scopes when `pessimistic_yield` is `true`.
     fixup_scopes: Vec<Scope>,
-    // Generated scope tree:
+    // The generated scope tree.
     scope_tree: ScopeTree,
 
     cx: Context,
@@ -411,7 +409,7 @@
     expr_and_pat_count: usize,
 }
 
-// This visitor has to have the same visit_expr calls as RegionResolutionVisitor
+// This visitor has to have the same `visit_expr` calls as `RegionResolutionVisitor`
 // since `expr_count` is compared against the results there.
 impl<'tcx> Visitor<'tcx> for ExprLocatorVisitor {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
@@ -456,7 +454,7 @@
             assert!(prev.is_none());
         }
 
-        // record the destruction scopes for later so we can query them
+        // Record the destruction scopes for later so we can query them.
         if let ScopeData::Destruction = child.data {
             self.destruction_scopes.insert(child.item_local_id(), child);
         }
@@ -478,7 +476,7 @@
         self.destruction_scopes.get(&n).cloned()
     }
 
-    /// Records that `sub_closure` is defined within `sup_closure`. These ids
+    /// Records that `sub_closure` is defined within `sup_closure`. These IDs
     /// should be the ID of the block that is the fn body, which is
     /// also the root of the region hierarchy for that fn.
     fn record_closure_parent(&mut self,
@@ -505,14 +503,14 @@
         self.rvalue_scopes.insert(var, lifetime);
     }
 
+    /// Returns the narrowest scope that encloses `id`, if any.
     pub fn opt_encl_scope(&self, id: Scope) -> Option<Scope> {
-        //! Returns the narrowest scope that encloses `id`, if any.
         self.parent_map.get(&id).cloned().map(|(p, _)| p)
     }
 
+    /// Returns the narrowest scope that encloses `id`, if any.
     #[allow(dead_code)] // used in cfg
     pub fn encl_scope(&self, id: Scope) -> Scope {
-        //! Returns the narrowest scope that encloses `id`, if any.
         self.opt_encl_scope(id).unwrap()
     }
 
@@ -522,16 +520,15 @@
             bug!("no enclosing scope for id {:?}", var_id))
     }
 
+    /// Returns the scope when the temp created by `expr_id` will be cleaned up.
     pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> Option<Scope> {
-        //! Returns the scope when temp created by expr_id will be cleaned up
-
-        // check for a designated rvalue scope
+        // Check for a designated rvalue scope.
         if let Some(&s) = self.rvalue_scopes.get(&expr_id) {
             debug!("temporary_scope({:?}) = {:?} [custom]", expr_id, s);
             return s;
         }
 
-        // else, locate the innermost terminating scope
+        // Otherwise, locate the innermost terminating scope
         // if there's one. Static items, for instance, won't
         // have an enclosing scope, hence no scope will be
         // returned.
@@ -552,9 +549,8 @@
         return None;
     }
 
+    /// Returns the lifetime of the variable `id`.
     pub fn var_region(&self, id: hir::ItemLocalId) -> ty::RegionKind {
-        //! Returns the lifetime of the variable `id`.
-
         let scope = ty::ReScope(self.var_scope(id));
         debug!("var_region({:?}) = {:?}", id, scope);
         scope
@@ -589,7 +585,7 @@
         return true;
     }
 
-    /// Returns the ID of the innermost containing body
+    /// Returns the ID of the innermost containing body.
     pub fn containing_body(&self, mut scope: Scope) -> Option<hir::ItemLocalId> {
         loop {
             if let ScopeData::CallSite = scope.data {
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index d02259b..c06a0fe 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -438,6 +438,7 @@
                     level: attr::StabilityLevel::Unstable {
                         reason: Some(Symbol::intern(reason)),
                         issue: 27812,
+                        is_soft: false,
                     },
                     feature: sym::rustc_private,
                     rustc_depr: None,
@@ -480,7 +481,7 @@
 }
 
 pub fn report_unstable(
-    sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, span: Span
+    sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, is_soft: bool, span: Span
 ) {
     let msg = match reason {
         Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
@@ -505,7 +506,13 @@
     let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone());
     let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id);
     if fresh {
-        emit_feature_err(&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg);
+        if is_soft {
+            sess.buffer_lint(lint::builtin::SOFT_UNSTABLE, CRATE_NODE_ID, span, &msg);
+        } else {
+            emit_feature_err(
+                &sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg
+            );
+        }
     }
 }
 
@@ -621,6 +628,7 @@
         feature: Symbol,
         reason: Option<Symbol>,
         issue: u32,
+        is_soft: bool,
     },
     /// The item does not have the `#[stable]` or `#[unstable]` marker assigned.
     Unmarked,
@@ -720,7 +728,9 @@
         }
 
         match stability {
-            Some(&Stability { level: attr::Unstable { reason, issue }, feature, .. }) => {
+            Some(&Stability {
+                level: attr::Unstable { reason, issue, is_soft }, feature, ..
+            }) => {
                 if span.allows_unstable(feature) {
                     debug!("stability: skipping span={:?} since it is internal", span);
                     return EvalResult::Allow;
@@ -744,7 +754,7 @@
                     }
                 }
 
-                EvalResult::Deny { feature, reason, issue }
+                EvalResult::Deny { feature, reason, issue, is_soft }
             }
             Some(_) => {
                 // Stable APIs are always ok to call and deprecated APIs are
@@ -767,8 +777,8 @@
     pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) {
         match self.eval_stability(def_id, id, span) {
             EvalResult::Allow => {}
-            EvalResult::Deny { feature, reason, issue } =>
-                report_unstable(self.sess, feature, reason, issue, span),
+            EvalResult::Deny { feature, reason, issue, is_soft } =>
+                report_unstable(self.sess, feature, reason, issue, is_soft, span),
             EvalResult::Unmarked => {
                 // The API could be uncallable for other reasons, for example when a private module
                 // was referenced.
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index 4fb88da..fa5fa22 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -116,8 +116,8 @@
 }
 
 impl<'a, 'tcx> Context<'a, 'tcx> {
-    fn register(&mut self, name: &str, span: Span) {
-        $(if name == stringify!($name) {
+    fn register(&mut self, name: Symbol, span: Span) {
+        $(if name == sym::$name {
             if self.items.$name().is_none() {
                 self.items.missing.push(lang_items::$item);
             }
@@ -136,7 +136,7 @@
 
     fn visit_foreign_item(&mut self, i: &hir::ForeignItem) {
         if let Some((lang_item, _)) = lang_items::extract(&i.attrs) {
-            self.register(&lang_item.as_str(), i.span);
+            self.register(lang_item, i.span);
         }
         intravisit::walk_foreign_item(self, i)
     }
diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs
index 3d33e24..1f60487 100644
--- a/src/librustc/mir/cache.rs
+++ b/src/librustc/mir/cache.rs
@@ -27,7 +27,7 @@
     fn hash_stable<W: StableHasherResult>(&self,
                                           _: &mut StableHashingContext<'a>,
                                           _: &mut StableHasher<W>) {
-        // do nothing
+        // Do nothing.
     }
 }
 
diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs
index 84b4cd9..15e6cb6 100644
--- a/src/librustc/mir/interpret/allocation.rs
+++ b/src/librustc/mir/interpret/allocation.rs
@@ -4,30 +4,46 @@
     Pointer, InterpResult, AllocId, ScalarMaybeUndef, write_target_uint, read_target_uint, Scalar,
 };
 
-use crate::ty::layout::{Size, Align};
-use syntax::ast::Mutability;
-use std::iter;
 use crate::mir;
-use std::ops::{Range, Deref, DerefMut};
+use crate::ty::layout::{Size, Align};
+
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_target::abi::HasDataLayout;
+use syntax::ast::Mutability;
+use std::iter;
+use std::ops::{Range, Deref, DerefMut};
 use std::borrow::Cow;
 
-#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
-pub struct Allocation<Tag=(),Extra=()> {
+// NOTE: When adding new fields, make sure to adjust the `Snapshot` impl in
+// `src/librustc_mir/interpret/snapshot.rs`.
+#[derive(
+    Clone,
+    Debug,
+    Eq,
+    PartialEq,
+    PartialOrd,
+    Ord,
+    Hash,
+    RustcEncodable,
+    RustcDecodable,
+    HashStable,
+)]
+pub struct Allocation<Tag = (),Extra = ()> {
     /// The actual bytes of the allocation.
-    /// Note that the bytes of a pointer represent the offset of the pointer
-    pub bytes: Vec<u8>,
+    /// Note that the bytes of a pointer represent the offset of the pointer.
+    bytes: Vec<u8>,
     /// Maps from byte addresses to extra data for each pointer.
     /// Only the first byte of a pointer is inserted into the map; i.e.,
     /// every entry in this map applies to `pointer_size` consecutive bytes starting
     /// at the given offset.
-    pub relocations: Relocations<Tag>,
-    /// Denotes undefined memory. Reading from undefined memory is forbidden in miri
-    pub undef_mask: UndefMask,
+    relocations: Relocations<Tag>,
+    /// Denotes which part of this allocation is initialized.
+    undef_mask: UndefMask,
+    /// The size of the allocation. Currently, must always equal `bytes.len()`.
+    pub size: Size,
     /// The alignment of the allocation to detect unaligned reads.
     pub align: Align,
-    /// Whether the allocation is mutable.
+    /// `true` if the allocation is mutable.
     /// Also used by codegen to determine if a static should be put into mutable memory,
     /// which happens for `static mut` and `static` with interior mutability.
     pub mutability: Mutability,
@@ -35,7 +51,6 @@
     pub extra: Extra,
 }
 
-
 pub trait AllocationExtra<Tag>: ::std::fmt::Debug + Clone {
     // There is no constructor in here because the constructor's type depends
     // on `MemoryKind`, and making things sufficiently generic leads to painful
@@ -77,7 +92,7 @@
     }
 }
 
-// For Tag=() and no extra state, we have is a trivial implementation.
+// For `Tag = ()` and no extra state, we have a trivial implementation.
 impl AllocationExtra<()> for () { }
 
 // The constructors are all without extra; the extra gets added by a machine hook later.
@@ -85,11 +100,12 @@
     /// Creates a read-only allocation initialized by the given bytes
     pub fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align) -> Self {
         let bytes = slice.into().into_owned();
-        let undef_mask = UndefMask::new(Size::from_bytes(bytes.len() as u64), true);
+        let size = Size::from_bytes(bytes.len() as u64);
         Self {
             bytes,
             relocations: Relocations::new(),
-            undef_mask,
+            undef_mask: UndefMask::new(size, true),
+            size,
             align,
             mutability: Mutability::Immutable,
             extra: (),
@@ -106,6 +122,7 @@
             bytes: vec![0; size.bytes() as usize],
             relocations: Relocations::new(),
             undef_mask: UndefMask::new(size, false),
+            size,
             align,
             mutability: Mutability::Mutable,
             extra: (),
@@ -113,9 +130,62 @@
     }
 }
 
+impl Allocation<(), ()> {
+    /// Add Tag and Extra fields
+    pub fn with_tags_and_extra<T, E>(
+        self,
+        mut tagger: impl FnMut(AllocId) -> T,
+        extra: E,
+    ) -> Allocation<T, E> {
+        Allocation {
+            bytes: self.bytes,
+            size: self.size,
+            relocations: Relocations::from_presorted(
+                self.relocations.iter()
+                    // The allocations in the relocations (pointers stored *inside* this allocation)
+                    // all get the base pointer tag.
+                    .map(|&(offset, ((), alloc))| {
+                        let tag = tagger(alloc);
+                        (offset, (tag, alloc))
+                    })
+                    .collect()
+            ),
+            undef_mask: self.undef_mask,
+            align: self.align,
+            mutability: self.mutability,
+            extra,
+        }
+    }
+}
+
+/// Raw accessors. Provide access to otherwise private bytes.
+impl<Tag, Extra> Allocation<Tag, Extra> {
+    pub fn len(&self) -> usize {
+        self.size.bytes() as usize
+    }
+
+    /// Looks at a slice which may describe undefined bytes or describe a relocation. This differs
+    /// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the
+    /// edges) at all. It further ignores `AllocationExtra` callbacks.
+    /// This must not be used for reads affecting the interpreter execution.
+    pub fn inspect_with_undef_and_ptr_outside_interpreter(&self, range: Range<usize>) -> &[u8] {
+        &self.bytes[range]
+    }
+
+    /// Returns the undef mask.
+    pub fn undef_mask(&self) -> &UndefMask {
+        &self.undef_mask
+    }
+
+    /// Returns the relocation list.
+    pub fn relocations(&self) -> &Relocations<Tag> {
+        &self.relocations
+    }
+}
+
 impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {}
 
-/// Byte accessors
+/// Byte accessors.
 impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
     /// Just a small local helper function to avoid a bit of code repetition.
     /// Returns the range of this allocation that was meant.
@@ -125,16 +195,16 @@
         offset: Size,
         size: Size
     ) -> Range<usize> {
-        let end = offset + size; // this does overflow checking
+        let end = offset + size; // This does overflow checking.
         assert_eq!(
             end.bytes() as usize as u64, end.bytes(),
             "cannot handle this access on this host architecture"
         );
         let end = end.bytes() as usize;
         assert!(
-            end <= self.bytes.len(),
+            end <= self.len(),
             "Out-of-bounds access at offset {}, size {} in allocation of size {}",
-            offset.bytes(), size.bytes(), self.bytes.len()
+            offset.bytes(), size.bytes(), self.len()
         );
         (offset.bytes() as usize)..end
     }
@@ -162,7 +232,7 @@
             self.check_defined(ptr, size)?;
             self.check_relocations(cx, ptr, size)?;
         } else {
-            // We still don't want relocations on the *edges*
+            // We still don't want relocations on the *edges*.
             self.check_relocation_edges(cx, ptr, size)?;
         }
 
@@ -171,7 +241,7 @@
         Ok(&self.bytes[range])
     }
 
-    /// Check that these bytes are initialized and not pointer bytes, and then return them
+    /// Checks that these bytes are initialized and not pointer bytes, and then return them
     /// as a slice.
     ///
     /// It is the caller's responsibility to check bounds and alignment beforehand.
@@ -223,7 +293,7 @@
     }
 }
 
-/// Reading and writing
+/// Reading and writing.
 impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
     /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached
     /// before a `0` is found.
@@ -259,9 +329,9 @@
         allow_ptr_and_undef: bool,
     ) -> InterpResult<'tcx>
     {
-        // Check bounds and relocations on the edges
+        // Check bounds and relocations on the edges.
         self.get_bytes_with_undef_and_ptr(cx, ptr, size)?;
-        // Check undef and ptr
+        // Check undef and ptr.
         if !allow_ptr_and_undef {
             self.check_defined(ptr, size)?;
             self.check_relocations(cx, ptr, size)?;
@@ -302,12 +372,12 @@
         Ok(())
     }
 
-    /// Read a *non-ZST* scalar
+    /// Reads a *non-ZST* scalar.
     ///
-    /// zsts can't be read out of two reasons:
-    /// * byteorder cannot work with zero element buffers
-    /// * in order to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers
-    ///   being valid for ZSTs
+    /// ZSTs can't be read for two reasons:
+    /// * byte-order cannot work with zero-element buffers;
+    /// * in order to obtain a `Pointer`, we need to check for ZSTness anyway due to integer
+    ///   pointers being valid for ZSTs.
     ///
     /// It is the caller's responsibility to check bounds and alignment beforehand.
     pub fn read_scalar(
@@ -317,20 +387,20 @@
         size: Size
     ) -> InterpResult<'tcx, ScalarMaybeUndef<Tag>>
     {
-        // get_bytes_unchecked tests relocation edges
+        // `get_bytes_unchecked` tests relocation edges.
         let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?;
         // Undef check happens *after* we established that the alignment is correct.
-        // We must not return Ok() for unaligned pointers!
+        // We must not return `Ok()` for unaligned pointers!
         if self.check_defined(ptr, size).is_err() {
-            // this inflates undefined bytes to the entire scalar, even if only a few
-            // bytes are undefined
+            // This inflates undefined bytes to the entire scalar, even if only a few
+            // bytes are undefined.
             return Ok(ScalarMaybeUndef::Undef);
         }
-        // Now we do the actual reading
+        // Now we do the actual reading.
         let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap();
-        // See if we got a pointer
+        // See if we got a pointer.
         if size != cx.data_layout().pointer_size {
-            // *Now* better make sure that the inside also is free of relocations.
+            // *Now*, we better make sure that the inside is free of relocations too.
             self.check_relocations(cx, ptr, size)?;
         } else {
             match self.relocations.get(&ptr.offset) {
@@ -345,7 +415,7 @@
         Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size)))
     }
 
-    /// Read a pointer-sized scalar.
+    /// Reads a pointer-sized scalar.
     ///
     /// It is the caller's responsibility to check bounds and alignment beforehand.
     pub fn read_ptr_sized(
@@ -357,12 +427,12 @@
         self.read_scalar(cx, ptr, cx.data_layout().pointer_size)
     }
 
-    /// Write a *non-ZST* scalar
+    /// Writes a *non-ZST* scalar.
     ///
-    /// zsts can't be read out of two reasons:
-    /// * byteorder cannot work with zero element buffers
-    /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers
-    ///   being valid for ZSTs
+    /// ZSTs can't be read for two reasons:
+    /// * byte-order cannot work with zero-element buffers;
+    /// * in order to obtain a `Pointer`, we need to check for ZSTness anyway due to integer
+    ///   pointers being valid for ZSTs.
     ///
     /// It is the caller's responsibility to check bounds and alignment beforehand.
     pub fn write_scalar(
@@ -390,7 +460,7 @@
         let dst = self.get_bytes_mut(cx, ptr, type_size)?;
         write_target_uint(endian, dst, bytes).unwrap();
 
-        // See if we have to also write a relocation
+        // See if we have to also write a relocation.
         match val {
             Scalar::Ptr(val) => {
                 self.relocations.insert(
@@ -404,7 +474,7 @@
         Ok(())
     }
 
-    /// Write a pointer-sized scalar.
+    /// Writes a pointer-sized scalar.
     ///
     /// It is the caller's responsibility to check bounds and alignment beforehand.
     pub fn write_ptr_sized(
@@ -419,10 +489,10 @@
     }
 }
 
-/// Relocations
+/// Relocations.
 impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
-    /// Returns all relocations overlapping with the given ptr-offset pair.
-    pub fn relocations(
+    /// Returns all relocations overlapping with the given pointer-offset pair.
+    pub fn get_relocations(
         &self,
         cx: &impl HasDataLayout,
         ptr: Pointer<Tag>,
@@ -431,7 +501,7 @@
         // We have to go back `pointer_size - 1` bytes, as that one would still overlap with
         // the beginning of this range.
         let start = ptr.offset.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1);
-        let end = ptr.offset + size; // this does overflow checking
+        let end = ptr.offset + size; // This does overflow checking.
         self.relocations.range(Size::from_bytes(start)..end)
     }
 
@@ -443,7 +513,7 @@
         ptr: Pointer<Tag>,
         size: Size,
     ) -> InterpResult<'tcx> {
-        if self.relocations(cx, ptr, size).is_empty() {
+        if self.get_relocations(cx, ptr, size).is_empty() {
             Ok(())
         } else {
             throw_unsup!(ReadPointerAsBytes)
@@ -465,7 +535,7 @@
         // Find the start and end of the given range and its outermost relocations.
         let (first, last) = {
             // Find all relocations overlapping the given range.
-            let relocations = self.relocations(cx, ptr, size);
+            let relocations = self.get_relocations(cx, ptr, size);
             if relocations.is_empty() {
                 return Ok(());
             }
@@ -491,7 +561,7 @@
         Ok(())
     }
 
-    /// Error if there are relocations overlapping with the edges of the
+    /// Errors if there are relocations overlapping with the edges of the
     /// given memory range.
     #[inline]
     fn check_relocation_edges(
@@ -507,7 +577,7 @@
 }
 
 
-/// Undefined bytes
+/// Undefined bytes.
 impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
     /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes`
     /// error which will report the first byte which is undefined.
@@ -536,9 +606,97 @@
     }
 }
 
-/// Relocations
+/// Run-length encoding of the undef mask.
+/// Used to copy parts of a mask multiple times to another allocation.
+pub struct AllocationDefinedness {
+    /// The definedness of the first range.
+    initial: bool,
+    /// The lengths of ranges that are run-length encoded.
+    /// The definedness of the ranges alternate starting with `initial`.
+    ranges: smallvec::SmallVec::<[u64; 1]>,
+}
+
+/// Transferring the definedness mask to other allocations.
+impl<Tag, Extra> Allocation<Tag, Extra> {
+    /// Creates a run-length encoding of the undef mask.
+    pub fn compress_undef_range(
+        &self,
+        src: Pointer<Tag>,
+        size: Size,
+    ) -> AllocationDefinedness {
+        // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`),
+        // a naive undef mask copying algorithm would repeatedly have to read the undef mask from
+        // the source and write it to the destination. Even if we optimized the memory accesses,
+        // we'd be doing all of this `repeat` times.
+        // Therefor we precompute a compressed version of the undef mask of the source value and
+        // then write it back `repeat` times without computing any more information from the source.
+
+        // A precomputed cache for ranges of defined/undefined bits
+        // 0000010010001110 will become
+        // `[5, 1, 2, 1, 3, 3, 1]`,
+        // where each element toggles the state.
+
+        let mut ranges = smallvec::SmallVec::<[u64; 1]>::new();
+        let initial = self.undef_mask.get(src.offset);
+        let mut cur_len = 1;
+        let mut cur = initial;
+
+        for i in 1..size.bytes() {
+            // FIXME: optimize to bitshift the current undef block's bits and read the top bit.
+            if self.undef_mask.get(src.offset + Size::from_bytes(i)) == cur {
+                cur_len += 1;
+            } else {
+                ranges.push(cur_len);
+                cur_len = 1;
+                cur = !cur;
+            }
+        }
+
+        ranges.push(cur_len);
+
+        AllocationDefinedness { ranges, initial, }
+    }
+
+    /// Applies multiple instances of the run-length encoding to the undef mask.
+    pub fn mark_compressed_undef_range(
+        &mut self,
+        defined: &AllocationDefinedness,
+        dest: Pointer<Tag>,
+        size: Size,
+        repeat: u64,
+    ) {
+        // An optimization where we can just overwrite an entire range of definedness bits if
+        // they are going to be uniformly `1` or `0`.
+        if defined.ranges.len() <= 1 {
+            self.undef_mask.set_range_inbounds(
+                dest.offset,
+                dest.offset + size * repeat,
+                defined.initial,
+            );
+            return;
+        }
+
+        for mut j in 0..repeat {
+            j *= size.bytes();
+            j += dest.offset.bytes();
+            let mut cur = defined.initial;
+            for range in &defined.ranges {
+                let old_j = j;
+                j += range;
+                self.undef_mask.set_range_inbounds(
+                    Size::from_bytes(old_j),
+                    Size::from_bytes(j),
+                    cur,
+                );
+                cur = !cur;
+            }
+        }
+    }
+}
+
+/// Relocations.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct Relocations<Tag=(), Id=AllocId>(SortedMap<Size, (Tag, Id)>);
+pub struct Relocations<Tag = (), Id = AllocId>(SortedMap<Size, (Tag, Id)>);
 
 impl<Tag, Id> Relocations<Tag, Id> {
     pub fn new() -> Self {
@@ -566,6 +724,59 @@
     }
 }
 
+/// A partial, owned list of relocations to transfer into another allocation.
+pub struct AllocationRelocations<Tag> {
+    relative_relocations: Vec<(Size, (Tag, AllocId))>,
+}
+
+impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
+    pub fn prepare_relocation_copy(
+        &self,
+        cx: &impl HasDataLayout,
+        src: Pointer<Tag>,
+        size: Size,
+        dest: Pointer<Tag>,
+        length: u64,
+    ) -> AllocationRelocations<Tag> {
+        let relocations = self.get_relocations(cx, src, size);
+        if relocations.is_empty() {
+            return AllocationRelocations { relative_relocations: Vec::new() };
+        }
+
+        let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize));
+
+        for i in 0..length {
+            new_relocations.extend(
+                relocations
+                .iter()
+                .map(|&(offset, reloc)| {
+                    // compute offset for current repetition
+                    let dest_offset = dest.offset + (i * size);
+                    (
+                        // shift offsets from source allocation to destination allocation
+                        offset + dest_offset - src.offset,
+                        reloc,
+                    )
+                })
+            );
+        }
+
+        AllocationRelocations {
+            relative_relocations: new_relocations,
+        }
+    }
+
+    /// Applies a relocation copy.
+    /// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected
+    /// to be clear of relocations.
+    pub fn mark_relocation_range(
+        &mut self,
+        relocations: AllocationRelocations<Tag>,
+    ) {
+        self.relocations.insert_presorted(relocations.relative_relocations);
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Undefined byte tracking
 ////////////////////////////////////////////////////////////////////////////////
@@ -627,8 +838,8 @@
         let (blocka, bita) = bit_index(start);
         let (blockb, bitb) = bit_index(end);
         if blocka == blockb {
-            // first set all bits but the first `bita`
-            // then unset the last `64 - bitb` bits
+            // First set all bits except the first `bita`,
+            // then unset the last `64 - bitb` bits.
             let range = if bitb == 0 {
                 u64::max_value() << bita
             } else {
@@ -643,24 +854,24 @@
         }
         // across block boundaries
         if new_state {
-            // set bita..64 to 1
+            // Set `bita..64` to `1`.
             self.blocks[blocka] |= u64::max_value() << bita;
-            // set 0..bitb to 1
+            // Set `0..bitb` to `1`.
             if bitb != 0 {
                 self.blocks[blockb] |= u64::max_value() >> (64 - bitb);
             }
-            // fill in all the other blocks (much faster than one bit at a time)
+            // Fill in all the other blocks (much faster than one bit at a time).
             for block in (blocka + 1) .. blockb {
                 self.blocks[block] = u64::max_value();
             }
         } else {
-            // set bita..64 to 0
+            // Set `bita..64` to `0`.
             self.blocks[blocka] &= !(u64::max_value() << bita);
-            // set 0..bitb to 0
+            // Set `0..bitb` to `0`.
             if bitb != 0 {
                 self.blocks[blockb] &= !(u64::max_value() >> (64 - bitb));
             }
-            // fill in all the other blocks (much faster than one bit at a time)
+            // Fill in all the other blocks (much faster than one bit at a time).
             for block in (blocka + 1) .. blockb {
                 self.blocks[block] = 0;
             }
@@ -697,7 +908,7 @@
             let additional_blocks = amount.bytes() / Self::BLOCK_SIZE + 1;
             assert_eq!(additional_blocks as usize as u64, additional_blocks);
             self.blocks.extend(
-                // FIXME(oli-obk): optimize this by repeating `new_state as Block`
+                // FIXME(oli-obk): optimize this by repeating `new_state as Block`.
                 iter::repeat(0).take(additional_blocks as usize),
             );
         }
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index ef0e205..ac99ccd 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -1,23 +1,21 @@
-use std::{fmt, env};
+use super::{RawConst, Pointer, CheckInAllocMsg, ScalarMaybeUndef};
 
 use crate::hir;
 use crate::hir::map::definitions::DefPathData;
 use crate::mir;
 use crate::ty::{self, Ty, layout};
 use crate::ty::layout::{Size, Align, LayoutError};
-use rustc_target::spec::abi::Abi;
-use rustc_macros::HashStable;
-
-use super::{RawConst, Pointer, CheckInAllocMsg, ScalarMaybeUndef};
+use crate::ty::query::TyCtxtAt;
 
 use backtrace::Backtrace;
-
-use crate::ty::query::TyCtxtAt;
 use errors::DiagnosticBuilder;
-
+use rustc_macros::HashStable;
+use rustc_target::spec::abi::Abi;
 use syntax_pos::{Pos, Span};
 use syntax::symbol::Symbol;
 
+use std::{fmt, env};
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
 pub enum ErrorHandled {
     /// Already reported a lint or an error for this evaluation.
@@ -215,6 +213,15 @@
     eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
 }
 
+impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
+    fn from(err: ErrorHandled) -> Self {
+        match err {
+            ErrorHandled::Reported => err_inval!(ReferencedConstant),
+            ErrorHandled::TooGeneric => err_inval!(TooGeneric),
+        }.into()
+    }
+}
+
 impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
     fn from(kind: InterpError<'tcx>) -> Self {
         let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
@@ -315,6 +322,9 @@
     }
 }
 
+/// Error information for when the program we executed turned out not to actually be a valid
+/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
+/// where we work on generic code or execution does not have all information available.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum InvalidProgramInfo<'tcx> {
     /// Resolution can fail if we are in a too generic context.
@@ -344,6 +354,7 @@
     }
 }
 
+/// Error information for when the program caused Undefined Behavior.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum UndefinedBehaviorInfo {
     /// Free-form case. Only for errors that are never caught!
@@ -366,12 +377,19 @@
     }
 }
 
+/// Error information for when the program did something that might (or might not) be correct
+/// to do according to the Rust spec, but due to limitations in the interpreter, the
+/// operation could not be carried out. These limitations can differ between CTFE and the
+/// Miri engine, e.g., CTFE does not support casting pointers to "real" integers.
+///
+/// Currently, we also use this as fall-back error kind for errors that have not been
+/// categorized yet.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum UnsupportedOpInfo<'tcx> {
     /// Free-form case. Only for errors that are never caught!
     Unsupported(String),
 
-    // -- Everything below is not classified yet --
+    // -- Everything below is not categorized yet --
     FunctionAbiMismatch(Abi, Abi),
     FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
     FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
@@ -430,13 +448,13 @@
         match self {
             PointerOutOfBounds { ptr, msg, allocation_size } => {
                 write!(f, "{} failed: pointer must be in-bounds at offset {}, \
-                          but is outside bounds of allocation {} which has size {}",
+                           but is outside bounds of allocation {} which has size {}",
                     msg, ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes())
             },
             ValidationFailure(ref err) => {
                 write!(f, "type validation failed: {}", err)
             }
-            NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
+            NoMirFor(ref func) => write!(f, "no MIR for `{}`", func),
             FunctionAbiMismatch(caller_abi, callee_abi) =>
                 write!(f, "tried to call a function with ABI {:?} using caller ABI {:?}",
                     callee_abi, caller_abi),
@@ -451,9 +469,9 @@
             FunctionArgCountMismatch =>
                 write!(f, "tried to call a function with incorrect number of arguments"),
             ReallocatedWrongMemoryKind(ref old, ref new) =>
-                write!(f, "tried to reallocate memory from {} to {}", old, new),
+                write!(f, "tried to reallocate memory from `{}` to `{}`", old, new),
             DeallocatedWrongMemoryKind(ref old, ref new) =>
-                write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new),
+                write!(f, "tried to deallocate `{}` memory but gave `{}` as the kind", old, new),
             InvalidChar(c) =>
                 write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
             AlignmentCheckFailed { required, has } =>
@@ -462,7 +480,7 @@
             TypeNotPrimitive(ty) =>
                 write!(f, "expected primitive type, got {}", ty),
             PathNotFound(ref path) =>
-                write!(f, "Cannot find path {:?}", path),
+                write!(f, "cannot find path {:?}", path),
             IncorrectAllocationInformation(size, size2, align, align2) =>
                 write!(f, "incorrect alloc info: expected size {} and align {}, \
                            got size {} and align {}",
@@ -525,7 +543,7 @@
             InvalidBoolOp(_) =>
                 write!(f, "invalid boolean operation"),
             UnterminatedCString(_) =>
-                write!(f, "attempted to get length of a null terminated string, but no null \
+                write!(f, "attempted to get length of a null-terminated string, but no null \
                     found before end of allocation"),
             ReadUndefBytes(_) =>
                 write!(f, "attempted to read undefined bytes"),
@@ -538,6 +556,8 @@
     }
 }
 
+/// Error information for when the program exhausted the resources granted to it
+/// by the interpreter.
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum ResourceExhaustionInfo {
     /// The stack grew too big.
@@ -582,7 +602,7 @@
 
 impl fmt::Display for InterpError<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Forward `Display` to `Debug`
+        // Forward `Display` to `Debug`.
         write!(f, "{:?}", self)
     }
 }
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 1ec95c2..23433c2 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -1,4 +1,4 @@
-//! An interpreter for MIR used in CTFE and by miri
+//! An interpreter for MIR used in CTFE and by miri.
 
 #[macro_export]
 macro_rules! err_unsup {
@@ -107,21 +107,21 @@
 
 pub use self::pointer::{Pointer, PointerArithmetic, CheckInAllocMsg};
 
-use std::fmt;
 use crate::mir;
 use crate::hir::def_id::DefId;
 use crate::ty::{self, TyCtxt, Instance, subst::UnpackedKind};
+use crate::ty::codec::TyDecoder;
 use crate::ty::layout::{self, Size};
 use std::io;
+use std::fmt;
+use std::num::NonZeroU32;
+use std::sync::atomic::{AtomicU32, Ordering};
 use rustc_serialize::{Encoder, Decodable, Encodable};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::{Lock as Mutex, HashMapExt};
+use rustc_data_structures::sync::{Lock, HashMapExt};
 use rustc_data_structures::tiny_list::TinyList;
 use rustc_macros::HashStable;
 use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian};
-use crate::ty::codec::TyDecoder;
-use std::sync::atomic::{AtomicU32, Ordering};
-use std::num::NonZeroU32;
 
 /// Uniquely identifies a specific constant or static.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable, HashStable)]
@@ -152,8 +152,8 @@
     tcx: TyCtxt<'tcx>,
     alloc_id: AllocId,
 ) -> Result<(), E::Error> {
-    let alloc: GlobalAlloc<'tcx> =
-        tcx.alloc_map.lock().get(alloc_id).expect("no value for AllocId");
+    let alloc: GlobalAlloc<'tcx> = tcx.alloc_map.lock().get(alloc_id)
+        .expect("no value for given alloc ID");
     match alloc {
         GlobalAlloc::Memory(alloc) => {
             trace!("encoding {:?} with {:#?}", alloc_id, alloc);
@@ -166,8 +166,8 @@
             fn_instance.encode(encoder)?;
         }
         GlobalAlloc::Static(did) => {
-            // referring to statics doesn't need to know about their allocations,
-            // just about its DefId
+            // References to statics doesn't need to know about their allocations,
+            // just about its `DefId`.
             AllocDiscriminant::Static.encode(encoder)?;
             did.encode(encoder)?;
         }
@@ -187,19 +187,18 @@
 }
 
 pub struct AllocDecodingState {
-    // For each AllocId we keep track of which decoding state it's currently in.
-    decoding_state: Vec<Mutex<State>>,
+    // For each `AllocId`, we keep track of which decoding state it's currently in.
+    decoding_state: Vec<Lock<State>>,
     // The offsets of each allocation in the data stream.
     data_offsets: Vec<u32>,
 }
 
 impl AllocDecodingState {
-
     pub fn new_decoding_session(&self) -> AllocDecodingSession<'_> {
         static DECODER_SESSION_ID: AtomicU32 = AtomicU32::new(0);
         let counter = DECODER_SESSION_ID.fetch_add(1, Ordering::SeqCst);
 
-        // Make sure this is never zero
+        // Make sure this is never zero.
         let session_id = DecodingSessionId::new((counter & 0x7FFFFFFF) + 1).unwrap();
 
         AllocDecodingSession {
@@ -208,10 +207,10 @@
         }
     }
 
-    pub fn new(data_offsets: Vec<u32>) -> AllocDecodingState {
-        let decoding_state = vec![Mutex::new(State::Empty); data_offsets.len()];
+    pub fn new(data_offsets: Vec<u32>) -> Self {
+        let decoding_state = vec![Lock::new(State::Empty); data_offsets.len()];
 
-        AllocDecodingState {
+        Self {
             decoding_state,
             data_offsets,
         }
@@ -225,23 +224,23 @@
 }
 
 impl<'s> AllocDecodingSession<'s> {
-    // Decodes an AllocId in a thread-safe way.
+    /// Decodes an `AllocId` in a thread-safe way.
     pub fn decode_alloc_id<D>(&self, decoder: &mut D) -> Result<AllocId, D::Error>
     where
         D: TyDecoder<'tcx>,
     {
-        // Read the index of the allocation
+        // Read the index of the allocation.
         let idx = decoder.read_u32()? as usize;
         let pos = self.state.data_offsets[idx] as usize;
 
-        // Decode the AllocDiscriminant now so that we know if we have to reserve an
-        // AllocId.
+        // Decode the `AllocDiscriminant` now so that we know if we have to reserve an
+        // `AllocId`.
         let (alloc_kind, pos) = decoder.with_position(pos, |decoder| {
             let alloc_kind = AllocDiscriminant::decode(decoder)?;
             Ok((alloc_kind, decoder.position()))
         })?;
 
-        // Check the decoding state, see if it's already decoded or if we should
+        // Check the decoding state to see if it's already decoded or if we should
         // decode it here.
         let alloc_id = {
             let mut entry = self.state.decoding_state[idx].lock();
@@ -251,11 +250,11 @@
                     return Ok(alloc_id);
                 }
                 ref mut entry @ State::Empty => {
-                    // We are allowed to decode
+                    // We are allowed to decode.
                     match alloc_kind {
                         AllocDiscriminant::Alloc => {
                             // If this is an allocation, we need to reserve an
-                            // AllocId so we can decode cyclic graphs.
+                            // `AllocId` so we can decode cyclic graphs.
                             let alloc_id = decoder.tcx().alloc_map.lock().reserve();
                             *entry = State::InProgress(
                                 TinyList::new_single(self.session_id),
@@ -263,8 +262,8 @@
                             Some(alloc_id)
                         },
                         AllocDiscriminant::Fn | AllocDiscriminant::Static => {
-                            // Fns and statics cannot be cyclic and their AllocId
-                            // is determined later by interning
+                            // Fns and statics cannot be cyclic, and their `AllocId`
+                            // is determined later by interning.
                             *entry = State::InProgressNonAlloc(
                                 TinyList::new_single(self.session_id));
                             None
@@ -273,9 +272,9 @@
                 }
                 State::InProgressNonAlloc(ref mut sessions) => {
                     if sessions.contains(&self.session_id) {
-                        bug!("This should be unreachable")
+                        bug!("this should be unreachable");
                     } else {
-                        // Start decoding concurrently
+                        // Start decoding concurrently.
                         sessions.insert(self.session_id);
                         None
                     }
@@ -285,7 +284,7 @@
                         // Don't recurse.
                         return Ok(alloc_id)
                     } else {
-                        // Start decoding concurrently
+                        // Start decoding concurrently.
                         sessions.insert(self.session_id);
                         Some(alloc_id)
                     }
@@ -293,20 +292,20 @@
             }
         };
 
-        // Now decode the actual data
+        // Now decode the actual data.
         let alloc_id = decoder.with_position(pos, |decoder| {
             match alloc_kind {
                 AllocDiscriminant::Alloc => {
-                    let allocation = <&'tcx Allocation as Decodable>::decode(decoder)?;
-                    // We already have a reserved AllocId.
+                    let alloc = <&'tcx Allocation as Decodable>::decode(decoder)?;
+                    // We already have a reserved `AllocId`.
                     let alloc_id = alloc_id.unwrap();
-                    trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
-                    decoder.tcx().alloc_map.lock().set_alloc_id_same_memory(alloc_id, allocation);
+                    trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc);
+                    decoder.tcx().alloc_map.lock().set_alloc_id_same_memory(alloc_id, alloc);
                     Ok(alloc_id)
                 },
                 AllocDiscriminant::Fn => {
                     assert!(alloc_id.is_none());
-                    trace!("creating fn alloc id");
+                    trace!("creating fn alloc ID");
                     let instance = ty::Instance::decode(decoder)?;
                     trace!("decoded fn alloc instance: {:?}", instance);
                     let alloc_id = decoder.tcx().alloc_map.lock().create_fn_alloc(instance);
@@ -314,8 +313,9 @@
                 },
                 AllocDiscriminant::Static => {
                     assert!(alloc_id.is_none());
-                    trace!("creating extern static alloc id at");
+                    trace!("creating extern static alloc ID");
                     let did = DefId::decode(decoder)?;
+                    trace!("decoded static def-ID: {:?}", did);
                     let alloc_id = decoder.tcx().alloc_map.lock().create_static_alloc(did);
                     Ok(alloc_id)
                 }
@@ -340,7 +340,7 @@
 /// a static, or a "real" allocation with some data in it.
 #[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)]
 pub enum GlobalAlloc<'tcx> {
-    /// The alloc ID is used as a function pointer
+    /// The alloc ID is used as a function pointer.
     Function(Instance<'tcx>),
     /// The alloc ID points to a "lazy" static variable that did not get computed (yet).
     /// This is also used to break the cycle in recursive statics.
@@ -350,16 +350,17 @@
 }
 
 pub struct AllocMap<'tcx> {
-    /// Lets you know what an `AllocId` refers to.
+    /// Maps `AllocId`s to their corresponding allocations.
     alloc_map: FxHashMap<AllocId, GlobalAlloc<'tcx>>,
 
     /// Used to ensure that statics and functions only get one associated `AllocId`.
     /// Should never contain a `GlobalAlloc::Memory`!
-    /// FIXME: Should we just have two separate dedup maps for statics and functions each?
+    //
+    // FIXME: Should we just have two separate dedup maps for statics and functions each?
     dedup: FxHashMap<GlobalAlloc<'tcx>, AllocId>,
 
     /// The `AllocId` to assign to the next requested ID.
-    /// Always incremented, never gets smaller.
+    /// Always incremented; never gets smaller.
     next_id: AllocId,
 }
 
@@ -389,7 +390,7 @@
         next
     }
 
-    /// Reserve a new ID *if* this allocation has not been dedup-reserved before.
+    /// Reserves a new ID *if* this allocation has not been dedup-reserved before.
     /// Should only be used for function pointers and statics, we don't want
     /// to dedup IDs for "real" memory!
     fn reserve_and_set_dedup(&mut self, alloc: GlobalAlloc<'tcx>) -> AllocId {
@@ -430,17 +431,17 @@
             }
         });
         if is_generic {
-            // Get a fresh ID
+            // Get a fresh ID.
             let id = self.reserve();
             self.alloc_map.insert(id, GlobalAlloc::Function(instance));
             id
         } else {
-            // Deduplicate
+            // Deduplicate.
             self.reserve_and_set_dedup(GlobalAlloc::Function(instance))
         }
     }
 
-    /// Intern the `Allocation` and return a new `AllocId`, even if there's already an identical
+    /// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical
     /// `Allocation` with a different `AllocId`.
     /// Statics with identical content will still point to the same `Allocation`, i.e.,
     /// their data will be deduplicated through `Allocation` interning -- but they
@@ -465,19 +466,19 @@
     pub fn unwrap_memory(&self, id: AllocId) -> &'tcx Allocation {
         match self.get(id) {
             Some(GlobalAlloc::Memory(mem)) => mem,
-            _ => bug!("expected allocation id {} to point to memory", id),
+            _ => bug!("expected allocation ID {} to point to memory", id),
         }
     }
 
-    /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
+    /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
     /// call this function twice, even with the same `Allocation` will ICE the compiler.
     pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
         if let Some(old) = self.alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
-            bug!("tried to set allocation id {}, but it was already existing as {:#?}", id, old);
+            bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old);
         }
     }
 
-    /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
+    /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
     /// twice for the same `(AllocId, Allocation)` pair.
     fn set_alloc_id_same_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
         self.alloc_map.insert_same(id, GlobalAlloc::Memory(mem));
@@ -513,7 +514,7 @@
 // Methods to facilitate working with signed integers stored in a u128
 ////////////////////////////////////////////////////////////////////////////////
 
-/// Truncate `value` to `size` bits and then sign-extend it to 128 bits
+/// Truncates `value` to `size` bits and then sign-extend it to 128 bits
 /// (i.e., if it is negative, fill with 1's on the left).
 #[inline]
 pub fn sign_extend(value: u128, size: Size) -> u128 {
@@ -522,14 +523,14 @@
         // Truncated until nothing is left.
         return 0;
     }
-    // sign extend
+    // Sign-extend it.
     let shift = 128 - size;
-    // shift the unsigned value to the left
-    // and back to the right as signed (essentially fills with FF on the left)
+    // Shift the unsigned value to the left, then shift back to the right as signed
+    // (essentially fills with FF on the left).
     (((value << shift) as i128) >> shift) as u128
 }
 
-/// Truncate `value` to `size` bits.
+/// Truncates `value` to `size` bits.
 #[inline]
 pub fn truncate(value: u128, size: Size) -> u128 {
     let size = size.bits();
@@ -538,6 +539,6 @@
         return 0;
     }
     let shift = 128 - size;
-    // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
+    // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
     (value << shift) >> shift
 }
diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs
index b55e6bc..1bb4d9e 100644
--- a/src/librustc/mir/interpret/pointer.rs
+++ b/src/librustc/mir/interpret/pointer.rs
@@ -86,18 +86,17 @@
 
 impl<T: layout::HasDataLayout> PointerArithmetic for T {}
 
-
-/// Pointer is generic over the type that represents a reference to Allocations,
+/// `Pointer` is generic over the type that represents a reference to `Allocation`s,
 /// thus making it possible for the most convenient representation to be used in
 /// each context.
 ///
-/// Defaults to the index based and loosely coupled AllocId.
+/// Defaults to the index based and loosely coupled `AllocId`.
 ///
 /// Pointer is also generic over the `Tag` associated with each pointer,
 /// which is used to do provenance tracking during execution.
 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
          RustcEncodable, RustcDecodable, Hash, HashStable)]
-pub struct Pointer<Tag=(),Id=AllocId> {
+pub struct Pointer<Tag = (), Id = AllocId> {
     pub alloc_id: Id,
     pub offset: Size,
     pub tag: Tag,
@@ -117,7 +116,7 @@
     }
 }
 
-/// Produces a `Pointer` which points to the beginning of the Allocation
+/// Produces a `Pointer` which points to the beginning of the `Allocation`.
 impl From<AllocId> for Pointer {
     #[inline(always)]
     fn from(alloc_id: AllocId) -> Self {
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 3da5a65..b8bc741 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -17,8 +17,8 @@
     pub ty: Ty<'tcx>,
 }
 
-/// Represents a constant value in Rust. `Scalar` and `ScalarPair` are optimizations that
-/// match the `LocalState` optimizations for easy conversions between `Value` and `ConstValue`.
+/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
+/// array length computations, enum discriminants and the pattern matching logic.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord,
          RustcEncodable, RustcDecodable, Hash, HashStable)]
 pub enum ConstValue<'tcx> {
@@ -91,7 +91,7 @@
 /// of a simple value or a pointer into another `Allocation`
 #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd,
          RustcEncodable, RustcDecodable, Hash, HashStable)]
-pub enum Scalar<Tag=(), Id=AllocId> {
+pub enum Scalar<Tag = (), Id = AllocId> {
     /// The raw bytes of a simple value.
     Raw {
         /// The first `size` bytes of `data` are the value.
@@ -359,7 +359,7 @@
 
     #[inline(always)]
     pub fn assert_bits(self, target_size: Size) -> u128 {
-        self.to_bits(target_size).expect("Expected Raw bits but got a Pointer")
+        self.to_bits(target_size).expect("expected Raw bits but got a Pointer")
     }
 
     /// Do not call this method!  Use either `assert_ptr` or `force_ptr`.
@@ -374,7 +374,7 @@
 
     #[inline(always)]
     pub fn assert_ptr(self) -> Pointer<Tag> {
-        self.to_ptr().expect("Expected a Pointer but got Raw bits")
+        self.to_ptr().expect("expected a Pointer but got Raw bits")
     }
 
     /// Do not call this method!  Dispatch based on the type instead.
@@ -482,8 +482,8 @@
     }
 }
 
-#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub enum ScalarMaybeUndef<Tag=(), Id=AllocId> {
+#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, RustcEncodable, RustcDecodable)]
+pub enum ScalarMaybeUndef<Tag = (), Id = AllocId> {
     Scalar(Scalar<Tag, Id>),
     Undef,
 }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 5ac99ba..0ebc707 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -18,6 +18,7 @@
     self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
     UserTypeAnnotationIndex,
 };
+
 use polonius_engine::Atom;
 use rustc_data_structures::bit_set::BitMatrix;
 use rustc_data_structures::fx::FxHashSet;
@@ -31,7 +32,6 @@
 use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::fmt::{self, Debug, Display, Formatter, Write};
-use std::iter::FusedIterator;
 use std::ops::{Index, IndexMut};
 use std::slice;
 use std::vec::IntoIter;
@@ -70,7 +70,7 @@
 
 /// The various "big phases" that MIR goes through.
 ///
-/// Warning: ordering of variants is significant
+/// Warning: ordering of variants is significant.
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum MirPhase {
     Build = 0,
@@ -80,16 +80,16 @@
 }
 
 impl MirPhase {
-    /// Gets the index of the current MirPhase within the set of all MirPhases.
+    /// Gets the index of the current MirPhase within the set of all `MirPhase`s.
     pub fn phase_index(&self) -> usize {
         *self as usize
     }
 }
 
-/// Lowered representation of a single function.
+/// The lowered representation of a single function.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Body<'tcx> {
-    /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
+    /// A list of basic blocks. References to basic block use a newtyped index type `BasicBlock`
     /// that indexes into this vector.
     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
 
@@ -100,7 +100,7 @@
     /// us to see the difference and forego optimization on the inlined promoted items.
     pub phase: MirPhase,
 
-    /// List of source scopes; these are referenced by statements
+    /// A list of source scopes; these are referenced by statements
     /// and used for debuginfo. Indexed by a `SourceScope`.
     pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
 
@@ -108,10 +108,10 @@
     /// needn't) be tracked across crates.
     pub source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
 
-    /// Yields type of the function, if it is a generator.
+    /// The yield type of the function, if it is a generator.
     pub yield_ty: Option<Ty<'tcx>>,
 
-    /// Generator drop glue
+    /// Generator drop glue.
     pub generator_drop: Option<Box<Body<'tcx>>>,
 
     /// The layout of a generator. Produced by the state transformation.
@@ -124,10 +124,10 @@
     /// variables and temporaries.
     pub local_decls: LocalDecls<'tcx>,
 
-    /// User type annotations
+    /// User type annotations.
     pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
 
-    /// Number of arguments this function takes.
+    /// The number of arguments this function takes.
     ///
     /// Starting at local 1, `arg_count` locals will be provided by the caller
     /// and can be assumed to be initialized.
@@ -143,10 +143,11 @@
 
     /// Names and capture modes of all the closure upvars, assuming
     /// the first argument is either the closure or a reference to it.
+    //
     // NOTE(eddyb) This is *strictly* a temporary hack for codegen
     // debuginfo generation, and will be removed at some point.
-    // Do **NOT** use it for anything else, upvar information should not be
-    // in the MIR, please rely on local crate HIR or other side-channels.
+    // Do **NOT** use it for anything else; upvar information should not be
+    // in the MIR, so please rely on local crate HIR or other side-channels.
     pub __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
 
     /// Mark this MIR of a const context other than const functions as having converted a `&&` or
@@ -157,10 +158,10 @@
     /// List of places where control flow was destroyed. Used for error reporting.
     pub control_flow_destroyed: Vec<(Span, String)>,
 
-    /// A span representing this MIR, for error reporting
+    /// A span representing this MIR, for error reporting.
     pub span: Span,
 
-    /// A cache for various calculations
+    /// A cache for various calculations.
     cache: cache::Cache,
 }
 
@@ -177,7 +178,7 @@
         span: Span,
         control_flow_destroyed: Vec<(Span, String)>,
     ) -> Self {
-        // We need `arg_count` locals, and one for the return place
+        // We need `arg_count` locals, and one for the return place.
         assert!(
             local_decls.len() >= arg_count + 1,
             "expected at least {} locals, got {}",
@@ -384,12 +385,12 @@
         true
     }
 
-    /// Returns the return type, it always return first element from `local_decls` array
+    /// Returns the return type; it always return first element from `local_decls` array.
     pub fn return_ty(&self) -> Ty<'tcx> {
         self.local_decls[RETURN_PLACE].ty
     }
 
-    /// Gets the location of the terminator for the given block
+    /// Gets the location of the terminator for the given block.
     pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
         Location { block: bb, statement_index: self[bb].statements.len() }
     }
@@ -463,7 +464,7 @@
 /// Most passes can work with it as a whole, within a single function.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, HashStable)]
 pub struct SourceInfo {
-    /// Source span for the AST pertaining to this MIR entity.
+    /// The source span for the AST pertaining to this MIR entity.
     pub span: Span,
 
     /// The source scope, keeping track of which bindings can be
@@ -591,13 +592,13 @@
 /// Classifies locals into categories. See `Body::local_kind`.
 #[derive(PartialEq, Eq, Debug, HashStable)]
 pub enum LocalKind {
-    /// User-declared variable binding
+    /// User-declared variable binding.
     Var,
-    /// Compiler-introduced temporary
+    /// Compiler-introduced temporary.
     Temp,
-    /// Function argument
+    /// Function argument.
     Arg,
-    /// Location of function's return value
+    /// Location of function's return value.
     ReturnPointer,
 }
 
@@ -619,7 +620,7 @@
     /// (b) it gives a way to separate this case from the remaining cases
     ///     for diagnostics.
     pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
-    /// Span of the pattern in which this variable was bound.
+    /// The span of the pattern in which this variable was bound.
     pub pat_span: Span,
 }
 
@@ -721,12 +722,12 @@
 /// argument, or the return place.
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub struct LocalDecl<'tcx> {
-    /// `let mut x` vs `let x`.
+    /// Whether this is a mutable minding (i.e., `let x` or `let mut x`).
     ///
     /// Temporaries and the return place are always mutable.
     pub mutability: Mutability,
 
-    /// Some(binding_mode) if this corresponds to a user-declared local variable.
+    /// `Some(binding_mode)` if this corresponds to a user-declared local variable.
     ///
     /// This is solely used for local diagnostics when generating
     /// warnings/errors when compiling the current crate, and
@@ -760,7 +761,7 @@
     /// intervening statement context).
     pub is_block_tail: Option<BlockTailInfo>,
 
-    /// Type of this local.
+    /// The type of this local.
     pub ty: Ty<'tcx>,
 
     /// If the user manually ascribed a type to this variable,
@@ -769,7 +770,7 @@
     /// region inference.
     pub user_ty: UserTypeProjections,
 
-    /// Name of the local, used in debuginfo and pretty-printing.
+    /// The name of the local, used in debuginfo and pretty-printing.
     ///
     /// Note that function arguments can also have this set to `Some(_)`
     /// to generate better debuginfo.
@@ -837,8 +838,8 @@
     /// ROOT SCOPE
     ///  │{ argument x: &str }
     ///  │
-    ///  │ │{ #[allow(unused_mut)] } // this is actually split into 2 scopes
-    ///  │ │                        // in practice because I'm lazy.
+    ///  │ │{ #[allow(unused_mut)] } // This is actually split into 2 scopes
+    ///  │ │                         // in practice because I'm lazy.
     ///  │ │
     ///  │ │← x.source_info.scope
     ///  │ │← `x.parse().unwrap()`
@@ -852,7 +853,7 @@
     ///  │
     ///  │ │{ let x: u32 }
     ///  │ │← x.visibility_scope
-    ///  │ │← `drop(x)` // this accesses `x: u32`
+    ///  │ │← `drop(x)` // This accesses `x: u32`.
     /// ```
     pub source_info: SourceInfo,
 
@@ -1038,16 +1039,16 @@
 
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum TerminatorKind<'tcx> {
-    /// block should have one successor in the graph; we jump there
+    /// Block should have one successor in the graph; we jump there.
     Goto { target: BasicBlock },
 
-    /// operand evaluates to an integer; jump depending on its value
-    /// to one of the targets, and otherwise fallback to `otherwise`
+    /// Operand evaluates to an integer; jump depending on its value
+    /// to one of the targets, and otherwise fallback to `otherwise`.
     SwitchInt {
-        /// discriminant value being tested
+        /// The discriminant value being tested.
         discr: Operand<'tcx>,
 
-        /// type of value being tested
+        /// The type of value being tested.
         switch_ty: Ty<'tcx>,
 
         /// Possible values. The locations to branch to in each case
@@ -1057,6 +1058,7 @@
         /// Possible branch sites. The last element of this vector is used
         /// for the otherwise branch, so targets.len() == values.len() + 1
         /// should hold.
+        //
         // This invariant is quite non-obvious and also could be improved.
         // One way to make this invariant is to have something like this instead:
         //
@@ -1069,7 +1071,7 @@
     },
 
     /// Indicates that the landing pad is finished and unwinding should
-    /// continue. Emitted by build::scope::diverge_cleanup.
+    /// continue. Emitted by `build::scope::diverge_cleanup`.
     Resume,
 
     /// Indicates that the landing pad is finished and that the process
@@ -1083,10 +1085,10 @@
     /// Indicates a terminator that can never be reached.
     Unreachable,
 
-    /// Drop the Place
+    /// Drop the `Place`.
     Drop { location: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> },
 
-    /// Drop the Place and assign the new value over it. This ensures
+    /// Drop the `Place` and assign the new value over it. This ensures
     /// that the assignment to `P` occurs *even if* the destructor for
     /// place unwinds. Its semantics are best explained by the
     /// elaboration:
@@ -1119,9 +1121,9 @@
         unwind: Option<BasicBlock>,
     },
 
-    /// Block ends with a call of a converging function
+    /// Block ends with a call of a converging function.
     Call {
-        /// The function that’s being called
+        /// The function that’s being called.
         func: Operand<'tcx>,
         /// Arguments the function is called with.
         /// These are owned by the callee, which is free to modify them.
@@ -1132,7 +1134,7 @@
         destination: Option<(Place<'tcx>, BasicBlock)>,
         /// Cleanups to be done if the call unwinds.
         cleanup: Option<BasicBlock>,
-        /// Whether this is from a call in HIR, rather than from an overloaded
+        /// `true` if this is from a call in HIR rather than from an overloaded
         /// operator. True for overloaded function call.
         from_hir_call: bool,
     },
@@ -1147,40 +1149,40 @@
         cleanup: Option<BasicBlock>,
     },
 
-    /// A suspend point
+    /// A suspend point.
     Yield {
-        /// The value to return
+        /// The value to return.
         value: Operand<'tcx>,
-        /// Where to resume to
+        /// Where to resume to.
         resume: BasicBlock,
-        /// Cleanup to be done if the generator is dropped at this suspend point
+        /// Cleanup to be done if the generator is dropped at this suspend point.
         drop: Option<BasicBlock>,
     },
 
-    /// Indicates the end of the dropping of a generator
+    /// Indicates the end of the dropping of a generator.
     GeneratorDrop,
 
     /// A block where control flow only ever takes one real path, but borrowck
     /// needs to be more conservative.
     FalseEdges {
-        /// The target normal control flow will take
+        /// The target normal control flow will take.
         real_target: BasicBlock,
         /// A block control flow could conceptually jump to, but won't in
-        /// practice
+        /// practice.
         imaginary_target: BasicBlock,
     },
     /// A terminator for blocks that only take one path in reality, but where we
     /// reserve the right to unwind in borrowck, even if it won't happen in practice.
     /// This can arise in infinite loops with no function calls for example.
     FalseUnwind {
-        /// The target normal control flow will take
+        /// The target normal control flow will take.
         real_target: BasicBlock,
         /// The imaginary cleanup block link. This particular path will never be taken
         /// in practice, but in order to avoid fragility we want to always
         /// consider it in borrowck. We don't want to accept programs which
-        /// pass borrowck only when panic=abort or some assertions are disabled
-        /// due to release vs. debug mode builds. This needs to be an Option because
-        /// of the remove_noop_landing_pads and no_landing_pads passes
+        /// pass borrowck only when `panic=abort` or some assertions are disabled
+        /// due to release vs. debug mode builds. This needs to be an `Option` because
+        /// of the `remove_noop_landing_pads` and `no_landing_pads` passes.
         unwind: Option<BasicBlock>,
     },
 }
@@ -1445,7 +1447,7 @@
 }
 
 impl<'tcx> TerminatorKind<'tcx> {
-    /// Write the "head" part of the terminator; that is, its name and the data it uses to pick the
+    /// Writes the "head" part of the terminator; that is, its name and the data it uses to pick the
     /// successor basic block, if any. The only information not included is the list of possible
     /// successors, which may be rendered differently between the text and the graphviz format.
     pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
@@ -1545,7 +1547,7 @@
 
 // `Statement` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert_size!(Statement<'_>, 56);
+static_assert_size!(Statement<'_>, 32);
 
 impl Statement<'_> {
     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
@@ -1566,7 +1568,7 @@
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub enum StatementKind<'tcx> {
     /// Write the RHS Rvalue to the LHS Place.
-    Assign(Place<'tcx>, Box<Rvalue<'tcx>>),
+    Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
 
     /// This represents all the reading that a pattern match may do
     /// (e.g., inspecting constants and discriminant values), and the
@@ -1575,10 +1577,10 @@
     ///
     /// Note that this also is emitted for regular `let` bindings to ensure that locals that are
     /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
-    FakeRead(FakeReadCause, Place<'tcx>),
+    FakeRead(FakeReadCause, Box<Place<'tcx>>),
 
     /// Write the discriminant for a variant to the enum Place.
-    SetDiscriminant { place: Place<'tcx>, variant_index: VariantIdx },
+    SetDiscriminant { place: Box<Place<'tcx>>, variant_index: VariantIdx },
 
     /// Start a live range for the storage of the local.
     StorageLive(Local),
@@ -1595,7 +1597,7 @@
     /// by miri and only generated when "-Z mir-emit-retag" is passed.
     /// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
     /// for more details.
-    Retag(RetagKind, Place<'tcx>),
+    Retag(RetagKind, Box<Place<'tcx>>),
 
     /// Encodes a user's type ascription. These need to be preserved
     /// intact so that NLL can respect them. For example:
@@ -1609,26 +1611,26 @@
     /// - `Contravariant` -- requires that `T_y :> T`
     /// - `Invariant` -- requires that `T_y == T`
     /// - `Bivariant` -- no effect
-    AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection>),
+    AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance),
 
     /// No-op. Useful for deleting instructions without affecting statement indices.
     Nop,
 }
 
-/// `RetagKind` describes what kind of retag is to be performed.
+/// Describes what kind of retag is to be performed.
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, HashStable)]
 pub enum RetagKind {
-    /// The initial retag when entering a function
+    /// The initial retag when entering a function.
     FnEntry,
-    /// Retag preparing for a two-phase borrow
+    /// Retag preparing for a two-phase borrow.
     TwoPhase,
-    /// Retagging raw pointers
+    /// Retagging raw pointers.
     Raw,
-    /// A "normal" retag
+    /// A "normal" retag.
     Default,
 }
 
-/// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists.
+/// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum FakeReadCause {
     /// Inject a fake read of the borrowed input at the end of each guards
@@ -1673,7 +1675,7 @@
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         use self::StatementKind::*;
         match self.kind {
-            Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
+            Assign(box(ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv),
             FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
             Retag(ref kind, ref place) => write!(
                 fmt,
@@ -1694,7 +1696,7 @@
             InlineAsm(ref asm) => {
                 write!(fmt, "asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs)
             }
-            AscribeUserType(ref place, ref variance, ref c_ty) => {
+            AscribeUserType(box(ref place, ref c_ty), ref variance) => {
                 write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
             }
             Nop => write!(fmt, "nop"),
@@ -1714,7 +1716,7 @@
     pub base: PlaceBase<'tcx>,
 
     /// projection out of a place (access a field, deref a pointer, etc)
-    pub projection: Option<Box<Projection<'tcx>>>,
+    pub projection: Box<[PlaceElem<'tcx>]>,
 }
 
 #[derive(
@@ -1757,15 +1759,6 @@
     def_id
 });
 
-/// The `Projection` data structure defines things of the form `base.x`, `*b` or `b[index]`.
-#[derive(
-    Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
-)]
-pub struct Projection<'tcx> {
-    pub base: Option<Box<Projection<'tcx>>>,
-    pub elem: PlaceElem<'tcx>,
-}
-
 #[derive(
     Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
 )]
@@ -1808,6 +1801,23 @@
     Downcast(Option<Symbol>, VariantIdx),
 }
 
+impl<V, T> ProjectionElem<V, T> {
+    /// Returns `true` if the target of this projection may refer to a different region of memory
+    /// than the base.
+    fn is_indirect(&self) -> bool {
+        match self {
+            Self::Deref => true,
+
+            | Self::Field(_, _)
+            | Self::Index(_)
+            | Self::ConstantIndex { .. }
+            | Self::Subslice { .. }
+            | Self::Downcast(_, _)
+            => false
+        }
+    }
+}
+
 /// Alias for projections as they appear in places, where the base is a place
 /// and the index is a local.
 pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
@@ -1830,14 +1840,22 @@
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct PlaceRef<'a, 'tcx> {
     pub base: &'a PlaceBase<'tcx>,
-    pub projection: &'a Option<Box<Projection<'tcx>>>,
+    pub projection: &'a [PlaceElem<'tcx>],
 }
 
 impl<'tcx> Place<'tcx> {
-    pub const RETURN_PLACE: Place<'tcx> = Place {
-        base: PlaceBase::Local(RETURN_PLACE),
-        projection: None,
-    };
+    // FIXME change this back to a const when projection is a shared slice.
+    //
+    // pub const RETURN_PLACE: Place<'tcx> = Place {
+    //     base: PlaceBase::Local(RETURN_PLACE),
+    //     projection: &[],
+    // };
+    pub fn return_place() -> Place<'tcx> {
+        Place {
+            base: PlaceBase::Local(RETURN_PLACE),
+            projection: Box::new([]),
+        }
+    }
 
     pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
         self.elem(ProjectionElem::Field(f, ty))
@@ -1863,12 +1881,24 @@
     }
 
     pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
+        // FIXME(spastorino): revisit this again once projection is not a Box<[T]> anymore
+        let mut projection = self.projection.into_vec();
+        projection.push(elem);
+
         Place {
             base: self.base,
-            projection: Some(Box::new(Projection { base: self.projection, elem })),
+            projection: projection.into_boxed_slice(),
         }
     }
 
+    /// Returns `true` if this `Place` contains a `Deref` projection.
+    ///
+    /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the
+    /// same region of memory as its base.
+    pub fn is_indirect(&self) -> bool {
+        self.projection.iter().any(|elem| elem.is_indirect())
+    }
+
     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
     /// a single deref of a local.
     //
@@ -1877,61 +1907,16 @@
         match self {
             Place {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: box [],
             } |
             Place {
                 base: PlaceBase::Local(local),
-                projection: Some(box Projection {
-                    base: None,
-                    elem: ProjectionElem::Deref,
-                }),
+                projection: box [ProjectionElem::Deref],
             } => Some(*local),
             _ => None,
         }
     }
 
-    /// Recursively "iterates" over place components, generating a `PlaceBase` and
-    /// `Projections` list and invoking `op` with a `ProjectionsIter`.
-    pub fn iterate<R>(
-        &self,
-        op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
-    ) -> R {
-        Place::iterate_over(&self.base, &self.projection, op)
-    }
-
-    pub fn iterate_over<R>(
-        place_base: &PlaceBase<'tcx>,
-        place_projection: &Option<Box<Projection<'tcx>>>,
-        op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
-    ) -> R {
-        fn iterate_over2<'tcx, R>(
-            place_base: &PlaceBase<'tcx>,
-            place_projection: &Option<Box<Projection<'tcx>>>,
-            next: &Projections<'_, 'tcx>,
-            op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
-        ) -> R {
-            match place_projection {
-                None => {
-                    op(place_base, next.iter())
-                }
-
-                Some(interior) => {
-                    iterate_over2(
-                        place_base,
-                        &interior.base,
-                        &Projections::List {
-                            projection: interior,
-                            next,
-                        },
-                        op,
-                    )
-                }
-            }
-        }
-
-        iterate_over2(place_base, place_projection, &Projections::Empty, op)
-    }
-
     pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
         PlaceRef {
             base: &self.base,
@@ -1944,7 +1929,7 @@
     fn from(local: Local) -> Self {
         Place {
             base: local.into(),
-            projection: None,
+            projection: Box::new([]),
         }
     }
 }
@@ -1956,13 +1941,6 @@
 }
 
 impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
-    pub fn iterate<R>(
-        &self,
-        op: impl FnOnce(&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>) -> R,
-    ) -> R {
-        Place::iterate_over(self.base, self.projection, op)
-    }
-
     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
     /// a single deref of a local.
     //
@@ -1971,143 +1949,71 @@
         match self {
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: [],
             } |
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: Some(box Projection {
-                    base: None,
-                    elem: ProjectionElem::Deref,
-                }),
+                projection: [ProjectionElem::Deref],
             } => Some(*local),
             _ => None,
         }
     }
 }
 
-/// A linked list of projections running up the stack; begins with the
-/// innermost projection and extends to the outermost (e.g., `a.b.c`
-/// would have the place `b` with a "next" pointer to `b.c`).
-/// Created by `Place::iterate`.
-///
-/// N.B., this particular impl strategy is not the most obvious. It was
-/// chosen because it makes a measurable difference to NLL
-/// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot.
-pub enum Projections<'p, 'tcx> {
-    Empty,
-
-    List { projection: &'p Projection<'tcx>, next: &'p Projections<'p, 'tcx> },
-}
-
-impl<'p, 'tcx> Projections<'p, 'tcx> {
-    fn iter(&self) -> ProjectionsIter<'_, 'tcx> {
-        ProjectionsIter { value: self }
-    }
-}
-
-impl<'p, 'tcx> IntoIterator for &'p Projections<'p, 'tcx> {
-    type Item = &'p Projection<'tcx>;
-    type IntoIter = ProjectionsIter<'p, 'tcx>;
-
-    /// Converts a list of `Projection` components into an iterator;
-    /// this iterator yields up a never-ending stream of `Option<&Place>`.
-    /// These begin with the "innermost" projection and then with each
-    /// projection therefrom. So given a place like `a.b.c` it would
-    /// yield up:
-    ///
-    /// ```notrust
-    /// Some(`a`), Some(`a.b`), Some(`a.b.c`), None, None, ...
-    /// ```
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter()
-    }
-}
-
-/// Iterator over components; see `Projections::iter` for more
-/// information.
-///
-/// N.B., this is not a *true* Rust iterator -- the code above just
-/// manually invokes `next`. This is because we (sometimes) want to
-/// keep executing even after `None` has been returned.
-pub struct ProjectionsIter<'p, 'tcx> {
-    pub value: &'p Projections<'p, 'tcx>,
-}
-
-impl<'p, 'tcx> Iterator for ProjectionsIter<'p, 'tcx> {
-    type Item = &'p Projection<'tcx>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        if let &Projections::List { projection, next } = self.value {
-            self.value = next;
-            Some(projection)
-        } else {
-            None
-        }
-    }
-}
-
-impl<'p, 'tcx> FusedIterator for ProjectionsIter<'p, 'tcx> {}
-
 impl Debug for Place<'_> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
-        self.iterate(|_place_base, place_projections| {
-            // FIXME: remove this collect once we have migrated to slices
-            let projs_vec: Vec<_> = place_projections.collect();
-            for projection in projs_vec.iter().rev() {
-                match projection.elem {
-                    ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
-                        write!(fmt, "(").unwrap();
-                    }
-                    ProjectionElem::Deref => {
-                        write!(fmt, "(*").unwrap();
-                    }
-                    ProjectionElem::Index(_)
-                    | ProjectionElem::ConstantIndex { .. }
-                    | ProjectionElem::Subslice { .. } => {}
+        for elem in self.projection.iter().rev() {
+            match elem {
+                ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
+                    write!(fmt, "(").unwrap();
+                }
+                ProjectionElem::Deref => {
+                    write!(fmt, "(*").unwrap();
+                }
+                ProjectionElem::Index(_)
+                | ProjectionElem::ConstantIndex { .. }
+                | ProjectionElem::Subslice { .. } => {}
+            }
+        }
+
+        write!(fmt, "{:?}", self.base)?;
+
+        for elem in self.projection.iter() {
+            match elem {
+                ProjectionElem::Downcast(Some(name), _index) => {
+                    write!(fmt, " as {})", name)?;
+                }
+                ProjectionElem::Downcast(None, index) => {
+                    write!(fmt, " as variant#{:?})", index)?;
+                }
+                ProjectionElem::Deref => {
+                    write!(fmt, ")")?;
+                }
+                ProjectionElem::Field(field, ty) => {
+                    write!(fmt, ".{:?}: {:?})", field.index(), ty)?;
+                }
+                ProjectionElem::Index(ref index) => {
+                    write!(fmt, "[{:?}]", index)?;
+                }
+                ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => {
+                    write!(fmt, "[{:?} of {:?}]", offset, min_length)?;
+                }
+                ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => {
+                    write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
+                }
+                ProjectionElem::Subslice { from, to } if *to == 0 => {
+                    write!(fmt, "[{:?}:]", from)?;
+                }
+                ProjectionElem::Subslice { from, to } if *from == 0 => {
+                    write!(fmt, "[:-{:?}]", to)?;
+                }
+                ProjectionElem::Subslice { from, to } => {
+                    write!(fmt, "[{:?}:-{:?}]", from, to)?;
                 }
             }
-        });
+        }
 
-        self.iterate(|place_base, place_projections| {
-            write!(fmt, "{:?}", place_base)?;
-
-            for projection in place_projections {
-                match projection.elem {
-                    ProjectionElem::Downcast(Some(name), _index) => {
-                        write!(fmt, " as {})", name)?;
-                    }
-                    ProjectionElem::Downcast(None, index) => {
-                        write!(fmt, " as variant#{:?})", index)?;
-                    }
-                    ProjectionElem::Deref => {
-                        write!(fmt, ")")?;
-                    }
-                    ProjectionElem::Field(field, ty) => {
-                        write!(fmt, ".{:?}: {:?})", field.index(), ty)?;
-                    }
-                    ProjectionElem::Index(ref index) => {
-                        write!(fmt, "[{:?}]", index)?;
-                    }
-                    ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => {
-                        write!(fmt, "[{:?} of {:?}]", offset, min_length)?;
-                    }
-                    ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => {
-                        write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
-                    }
-                    ProjectionElem::Subslice { from, to } if to == 0 => {
-                        write!(fmt, "[{:?}:]", from)?;
-                    }
-                    ProjectionElem::Subslice { from, to } if from == 0 => {
-                        write!(fmt, "[:-{:?}]", to)?;
-                    }
-                    ProjectionElem::Subslice { from, to } => {
-                        write!(fmt, "[{:?}:-{:?}]", from, to)?;
-                    }
-                }
-            }
-
-            Ok(())
-        })
+        Ok(())
     }
 }
 
@@ -2146,7 +2052,7 @@
 
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub struct SourceScopeLocalData {
-    /// A HirId with lint levels equivalent to this scope's lint levels.
+    /// An `HirId` with lint levels equivalent to this scope's lint levels.
     pub lint_root: hir::HirId,
     /// The unsafe block that contains this node.
     pub safety: Safety,
@@ -2735,11 +2641,12 @@
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
 pub struct Location {
-    /// the location is within this block
+    /// The block that the location is within.
     pub block: BasicBlock,
 
-    /// the location is the start of the statement; or, if `statement_index`
-    /// == num-statements, then the start of the terminator.
+    /// The location is the position of the start of the statement; or, if
+    /// `statement_index` equals the number of statements, then the start of the
+    /// terminator.
     pub statement_index: usize,
 }
 
@@ -2802,7 +2709,7 @@
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
 pub enum UnsafetyViolationKind {
     General,
-    /// Permitted in const fn and regular fns.
+    /// Permitted both in `const fn`s and regular `fn`s.
     GeneralAndConstFn,
     ExternStatic(hir::HirId),
     BorrowPacked(hir::HirId),
@@ -2818,9 +2725,9 @@
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
 pub struct UnsafetyCheckResult {
-    /// Violations that are propagated *upwards* from this function
+    /// Violations that are propagated *upwards* from this function.
     pub violations: Lrc<[UnsafetyViolation]>,
-    /// unsafe blocks in this function, along with whether they are used. This is
+    /// `unsafe` blocks in this function, along with whether they are used. This is
     /// used for the "unused_unsafe" lint.
     pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
 }
@@ -2832,7 +2739,7 @@
     }
 }
 
-/// The layout of generator state
+/// The layout of generator state.
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub struct GeneratorLayout<'tcx> {
     /// The type of every local stored inside the generator.
@@ -2847,11 +2754,14 @@
     /// layout.
     pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
 
-    /// Names and scopes of all the stored generator locals.
-    /// NOTE(tmandry) This is *strictly* a temporary hack for codegen
+    /// The names and scopes of all the stored generator locals.
+    ///
+    /// N.B., this is *strictly* a temporary hack for codegen
     /// debuginfo generation, and will be removed at some point.
     /// Do **NOT** use it for anything else, local information should not be
     /// in the MIR, please rely on local crate HIR or other side-channels.
+    //
+    // FIXME(tmandry): see above.
     pub __local_debuginfo_codegen_only_do_not_use: IndexVec<GeneratorSavedLocal, LocalDecl<'tcx>>,
 }
 
@@ -2909,7 +2819,7 @@
 /// instances assigned one of these same indices. Those regions will
 /// be substituted away by the creator. We use `ReClosureBound` in
 /// that case because the regions must be allocated in the global
-/// TyCtxt, and hence we cannot use `ReVar` (which is what we use
+/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use
 /// internally within the rest of the NLL code).
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub struct ClosureRegionRequirements<'tcx> {
@@ -2925,8 +2835,8 @@
     pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
 }
 
-/// Indicates an outlives constraint between a type or between two
-/// free-regions declared on the closure.
+/// Indicates an outlives-constraint between a type or between two
+/// free regions declared on the closure.
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub struct ClosureOutlivesRequirement<'tcx> {
     // This region or type ...
@@ -2942,11 +2852,11 @@
     pub category: ConstraintCategory,
 }
 
-/// Outlives constraints can be categorized to determine whether and why they
+/// Outlives-constraints can be categorized to determine whether and why they
 /// are interesting (for error reporting). Order of variants indicates sort
 /// order of the category, thereby influencing diagnostic output.
 ///
-/// See also [rustc_mir::borrow_check::nll::constraints]
+/// See also [rustc_mir::borrow_check::nll::constraints].
 #[derive(
     Copy,
     Clone,
@@ -2994,7 +2904,7 @@
     Internal,
 }
 
-/// The subject of a ClosureOutlivesRequirement -- that is, the thing
+/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
 /// that must outlive some region.
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub enum ClosureOutlivesSubject<'tcx> {
@@ -3012,7 +2922,7 @@
 }
 
 /*
- * TypeFoldable implementations for MIR types
+ * `TypeFoldable` implementations for MIR types
 */
 
 CloneTypeFoldableAndLiftImpls! {
@@ -3088,14 +2998,14 @@
 
 EnumTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> {
-        (StatementKind::Assign)(a, b),
+        (StatementKind::Assign)(a),
         (StatementKind::FakeRead)(cause, place),
         (StatementKind::SetDiscriminant) { place, variant_index },
         (StatementKind::StorageLive)(a),
         (StatementKind::StorageDead)(a),
         (StatementKind::InlineAsm)(a),
         (StatementKind::Retag)(kind, place),
-        (StatementKind::AscribeUserType)(a, v, b),
+        (StatementKind::AscribeUserType)(a, v),
         (StatementKind::Nop),
     }
 }
@@ -3377,30 +3287,26 @@
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for Projection<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         use crate::mir::ProjectionElem::*;
 
-        let base = self.base.fold_with(folder);
-        let elem = match self.elem {
+        match self {
             Deref => Deref,
-            Field(f, ref ty) => Field(f, ty.fold_with(folder)),
-            Index(ref v) => Index(v.fold_with(folder)),
-            ref elem => elem.clone(),
-        };
-
-        Projection { base, elem }
+            Field(f, ty) => Field(*f, ty.fold_with(folder)),
+            Index(v) => Index(v.fold_with(folder)),
+            elem => elem.clone(),
+        }
     }
 
     fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
         use crate::mir::ProjectionElem::*;
 
-        self.base.visit_with(visitor)
-            || match self.elem {
-                Field(_, ref ty) => ty.visit_with(visitor),
-                Index(ref v) => v.visit_with(visitor),
-                _ => false,
-            }
+        match self {
+            Field(_, ty) => ty.visit_with(visitor),
+            Index(v) => v.visit_with(visitor),
+            _ => false,
+        }
     }
 }
 
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index e9f7636..d776809 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -121,21 +121,16 @@
 impl<'tcx> Place<'tcx> {
     pub fn ty_from<D>(
         base: &PlaceBase<'tcx>,
-        projection: &Option<Box<Projection<'tcx>>>,
+        projection: &[PlaceElem<'tcx>],
         local_decls: &D,
         tcx: TyCtxt<'tcx>
     ) -> PlaceTy<'tcx>
         where D: HasLocalDecls<'tcx>
     {
-        Place::iterate_over(base, projection, |place_base, place_projections| {
-            let mut place_ty = place_base.ty(local_decls);
-
-            for proj in place_projections {
-                place_ty = place_ty.projection_ty(tcx, &proj.elem);
-            }
-
-            place_ty
-        })
+        projection.iter().fold(
+            base.ty(local_decls),
+            |place_ty, elem| place_ty.projection_ty(tcx, elem)
+        )
     }
 
     pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 821367e..1e3b9eb 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -152,18 +152,18 @@
             }
 
             fn visit_place_base(&mut self,
-                                place_base: & $($mutability)? PlaceBase<'tcx>,
+                                base: & $($mutability)? PlaceBase<'tcx>,
                                 context: PlaceContext,
                                 location: Location) {
-                self.super_place_base(place_base, context, location);
+                self.super_place_base(base, context, location);
             }
 
             fn visit_projection(&mut self,
-                                place_base: & $($mutability)? PlaceBase<'tcx>,
-                                place: & $($mutability)? Projection<'tcx>,
+                                base: & $($mutability)? PlaceBase<'tcx>,
+                                projection: & $($mutability)? [PlaceElem<'tcx>],
                                 context: PlaceContext,
                                 location: Location) {
-                self.super_projection(place_base, place, context, location);
+                self.super_projection(base, projection, context, location);
             }
 
             fn visit_constant(&mut self,
@@ -344,7 +344,9 @@
 
                 self.visit_source_info(source_info);
                 match kind {
-                    StatementKind::Assign(place, rvalue) => {
+                    StatementKind::Assign(
+                        box(ref $($mutability)? place, ref $($mutability)? rvalue)
+                    ) => {
                         self.visit_assign(place, rvalue, location);
                     }
                     StatementKind::FakeRead(_, place) => {
@@ -391,7 +393,10 @@
                     StatementKind::Retag(kind, place) => {
                         self.visit_retag(kind, place, location);
                     }
-                    StatementKind::AscribeUserType(place, variance, user_ty) => {
+                    StatementKind::AscribeUserType(
+                        box(ref $($mutability)? place, ref $($mutability)? user_ty),
+                        variance
+                    ) => {
                         self.visit_ascribe_user_ty(place, variance, user_ty, location);
                     }
                     StatementKind::Nop => {}
@@ -685,7 +690,7 @@
                             location: Location) {
                 let mut context = context;
 
-                if place.projection.is_some() {
+                if !place.projection.is_empty() {
                     context = if context.is_mutating_use() {
                         PlaceContext::MutatingUse(MutatingUseContext::Projection)
                     } else {
@@ -695,9 +700,10 @@
 
                 self.visit_place_base(& $($mutability)? place.base, context, location);
 
-                if let Some(box proj) = & $($mutability)? place.projection {
-                    self.visit_projection(& $($mutability)? place.base, proj, context, location);
-                }
+                self.visit_projection(& $($mutability)? place.base,
+                                      & $($mutability)? place.projection,
+                                      context,
+                                      location);
             }
 
             fn super_place_base(&mut self,
@@ -715,31 +721,31 @@
             }
 
             fn super_projection(&mut self,
-                                place_base: & $($mutability)? PlaceBase<'tcx>,
-                                proj: & $($mutability)? Projection<'tcx>,
+                                base: & $($mutability)? PlaceBase<'tcx>,
+                                projection: & $($mutability)? [PlaceElem<'tcx>],
                                 context: PlaceContext,
                                 location: Location) {
-                if let Some(box proj_base) = & $($mutability)? proj.base {
-                    self.visit_projection(place_base, proj_base, context, location);
-                }
+                if let [proj_base @ .., elem] = projection {
+                    self.visit_projection(base, proj_base, context, location);
 
-                match & $($mutability)? proj.elem {
-                    ProjectionElem::Field(_field, ty) => {
-                        self.visit_ty(ty, TyContext::Location(location));
-                    }
-                    ProjectionElem::Index(local) => {
-                        self.visit_local(
-                            local,
-                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
-                            location
-                        );
-                    }
-                    ProjectionElem::Deref |
-                    ProjectionElem::Subslice { from: _, to: _ } |
-                    ProjectionElem::ConstantIndex { offset: _,
-                                                    min_length: _,
-                                                    from_end: _ } |
-                    ProjectionElem::Downcast(_, _) => {
+                    match elem {
+                        ProjectionElem::Field(_field, ty) => {
+                            self.visit_ty(ty, TyContext::Location(location));
+                        }
+                        ProjectionElem::Index(local) => {
+                            self.visit_local(
+                                local,
+                                PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
+                                location
+                            );
+                        }
+                        ProjectionElem::Deref |
+                        ProjectionElem::Subslice { from: _, to: _ } |
+                        ProjectionElem::ConstantIndex { offset: _,
+                                                        min_length: _,
+                                                        from_end: _ } |
+                        ProjectionElem::Downcast(_, _) => {
+                        }
                     }
                 }
             }
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index ef83811..c726094 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -17,7 +17,6 @@
 use std::borrow::Cow;
 use syntax_pos::symbol::InternedString;
 
-
 // Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
@@ -463,15 +462,6 @@
             no_force
             desc { "extract field of const" }
         }
-
-        /// Produces an absolute path representation of the given type. See also the documentation
-        /// on `std::any::type_name`.
-        query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
-            eval_always
-            no_force
-            desc { "get absolute path of type" }
-        }
-
     }
 
     TypeChecking {
@@ -854,7 +844,7 @@
             desc { "calculating the lang items map" }
         }
 
-        /// Returns all diagnostic items defined in all crates
+        /// Returns all diagnostic items defined in all crates.
         query all_diagnostic_items(_: CrateNum) -> &'tcx FxHashMap<Symbol, DefId> {
             eval_always
             desc { "calculating the diagnostic items map" }
@@ -865,7 +855,7 @@
             desc { "calculating the lang items defined in a crate" }
         }
 
-        /// Returns the diagnostic items defined in a crate
+        /// Returns the diagnostic items defined in a crate.
         query diagnostic_items(_: CrateNum) -> &'tcx FxHashMap<Symbol, DefId> {
             desc { "calculating the diagnostic items map in a crate" }
         }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 740d9db..723855c 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1,36 +1,38 @@
 //! Contains infrastructure for configuring the compiler, including parsing
-//! command line options.
+//! command-line options.
 
-use std::str::FromStr;
-
+use crate::lint;
+use crate::middle::cstore;
 use crate::session::{early_error, early_warn, Session};
 use crate::session::search_paths::SearchPath;
 
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lrc;
+
 use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
 use rustc_target::spec::{Target, TargetTriple};
-use crate::lint;
-use crate::middle::cstore;
 
 use syntax;
 use syntax::ast::{self, IntTy, UintTy, MetaItemKind};
 use syntax::source_map::{FileName, FilePathMapping};
 use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
+use syntax::parse::{ParseSess, new_parser_from_source_str};
 use syntax::parse::token;
-use syntax::parse;
 use syntax::symbol::{sym, Symbol};
 use syntax::feature_gate::UnstableFeatures;
-use errors::emitter::HumanReadableErrorType;
+use syntax::source_map::SourceMap;
 
+use errors::emitter::HumanReadableErrorType;
 use errors::{ColorConfig, FatalError, Handler};
 
 use getopts;
-use std::collections::{BTreeMap, BTreeSet};
-use std::collections::btree_map::Iter as BTreeMapIter;
-use std::collections::btree_map::Keys as BTreeMapKeysIter;
-use std::collections::btree_map::Values as BTreeMapValuesIter;
 
-use rustc_data_structures::fx::FxHashSet;
-use std::{fmt, str};
+use std::collections::{BTreeMap, BTreeSet};
+use std::collections::btree_map::{
+    Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
+};
+use std::fmt;
+use std::str::{self, FromStr};
 use std::hash::Hasher;
 use std::collections::hash_map::DefaultHasher;
 use std::iter::FromIterator;
@@ -241,14 +243,14 @@
 }
 
 impl Default for ErrorOutputType {
-    fn default() -> ErrorOutputType {
-        ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto))
+    fn default() -> Self {
+        Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto))
     }
 }
 
-// Use tree-based collections to cheaply get a deterministic Hash implementation.
-// DO NOT switch BTreeMap out for an unsorted container type! That would break
-// dependency tracking for command-line arguments.
+/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
+/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
+/// dependency tracking for command-line arguments.
 #[derive(Clone, Hash)]
 pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
 
@@ -281,7 +283,7 @@
         self.0.len()
     }
 
-    // True if any of the output types require codegen or linking.
+    // Returns `true` if any of the output types require codegen or linking.
     pub fn should_codegen(&self) -> bool {
         self.0.keys().any(|k| match *k {
             OutputType::Bitcode
@@ -295,9 +297,9 @@
     }
 }
 
-// Use tree-based collections to cheaply get a deterministic Hash implementation.
-// DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That
-// would break dependency tracking for command-line arguments.
+/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
+/// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That
+/// would break dependency tracking for command-line arguments.
 #[derive(Clone, Hash)]
 pub struct Externs(BTreeMap<String, ExternEntry>);
 
@@ -327,7 +329,7 @@
     ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({
         if $sub_hashes.insert(stringify!($opt_name),
                               $opt_expr as &dyn dep_tracking::DepTrackingHash).is_some() {
-            bug!("Duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
+            bug!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
         }
     });
 }
@@ -362,7 +364,7 @@
     );
 }
 
-// The top-level command-line options struct
+// The top-level command-line options struct.
 //
 // For each option, one has to specify how it behaves with regard to the
 // dependency tracking system of incremental compilation. This is done via the
@@ -376,16 +378,16 @@
 // Incremental compilation is not influenced by this option.
 //
 // If you add a new option to this struct or one of the sub-structs like
-// CodegenOptions, think about how it influences incremental compilation. If in
+// `CodegenOptions`, think about how it influences incremental compilation. If in
 // doubt, specify [TRACKED], which is always "correct" but might lead to
 // unnecessary re-compilation.
 top_level_options!(
     pub struct Options {
         // The crate config requested for the session, which may be combined
-        // with additional crate configurations during the compile process
+        // with additional crate configurations during the compile process.
         crate_types: Vec<CrateType> [TRACKED],
         optimize: OptLevel [TRACKED],
-        // Include the debug_assertions flag into dependency tracking, since it
+        // Include the `debug_assertions` flag in dependency tracking, since it
         // can influence whether overflow checks are done or not.
         debug_assertions: bool [TRACKED],
         debuginfo: DebugInfo [TRACKED],
@@ -402,8 +404,8 @@
         test: bool [TRACKED],
         error_format: ErrorOutputType [UNTRACKED],
 
-        // if Some, enable incremental compilation, using the given
-        // directory to store intermediate results
+        // If `Some`, enable incremental compilation, using the given
+        // directory to store intermediate results.
         incremental: Option<PathBuf> [UNTRACKED],
 
         debugging_opts: DebuggingOptions [TRACKED],
@@ -418,7 +420,7 @@
         // written `extern crate name as std`. Defaults to `std`. Used by
         // out-of-tree drivers.
         alt_std_name: Option<String> [TRACKED],
-        // Indicates how the compiler should treat unstable features
+        // Indicates how the compiler should treat unstable features.
         unstable_features: UnstableFeatures [TRACKED],
 
         // Indicates whether this run of the compiler is actually rustdoc. This
@@ -434,12 +436,12 @@
         cli_forced_codegen_units: Option<usize> [UNTRACKED],
         cli_forced_thinlto_off: bool [UNTRACKED],
 
-        // Remap source path prefixes in all output (messages, object files, debug, etc)
+        // Remap source path prefixes in all output (messages, object files, debug, etc.).
         remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
 
         edition: Edition [TRACKED],
 
-        // Whether or not we're emitting JSON blobs about each artifact produced
+        // `true` if we're emitting JSON blobs about each artifact produced
         // by the compiler.
         json_artifact_notifications: bool [TRACKED],
     }
@@ -468,7 +470,7 @@
 }
 
 impl BorrowckMode {
-    /// Should we run the MIR-based borrow check, but also fall back
+    /// Returns whether we should run the MIR-based borrow check, but also fall back
     /// on the AST borrow check if the MIR-based one errors.
     pub fn migrate(self) -> bool {
         match self {
@@ -477,7 +479,7 @@
         }
     }
 
-    /// Should we emit the AST-based borrow checker errors?
+    /// Returns whether we should emit the AST-based borrow checker errors.
     pub fn use_ast(self) -> bool {
         match self {
             BorrowckMode::Mir => false,
@@ -487,12 +489,13 @@
 }
 
 pub enum Input {
-    /// Loads source from file
+    /// Load source code from a file.
     File(PathBuf),
+    /// Load source code from a string.
     Str {
-        /// String that is shown in place of a filename
+        /// A string that is shown in place of a filename.
         name: FileName,
-        /// Anonymous source string
+        /// An anonymous string containing the source code.
         input: String,
     },
 }
@@ -651,7 +654,7 @@
         FilePathMapping::new(self.remap_path_prefix.clone())
     }
 
-    /// Returns `true` if there will be an output file generated
+    /// Returns `true` if there will be an output file generated.
     pub fn will_create_output_file(&self) -> bool {
         !self.debugging_opts.parse_only && // The file is just being parsed
             !self.debugging_opts.ls // The file is just being queried
@@ -709,16 +712,14 @@
     }
 }
 
-/// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all
-/// at once. The goal of this macro is to define an interface that can be
-/// programmatically used by the option parser in order to initialize the struct
-/// without hardcoding field names all over the place.
+/// Defines all `CodegenOptions`/`DebuggingOptions` fields and parsers all at once. The goal of this
+/// macro is to define an interface that can be programmatically used by the option parser
+/// to initialize the struct without hardcoding field names all over the place.
 ///
-/// The goal is to invoke this macro once with the correct fields, and then this
-/// macro generates all necessary code. The main gotcha of this macro is the
-/// cgsetters module which is a bunch of generated code to parse an option into
-/// its respective field in the struct. There are a few hand-written parsers for
-/// parsing specific types of values in this module.
+/// The goal is to invoke this macro once with the correct fields, and then this macro generates all
+/// necessary code. The main gotcha of this macro is the `cgsetters` module which is a bunch of
+/// generated code to parse an option into its respective field in the struct. There are a few
+/// hand-written parsers for parsing specific types of values in this module.
 macro_rules! options {
     ($struct_name:ident, $setter_name:ident, $defaultfn:ident,
      $buildfn:ident, $prefix:expr, $outputname:expr,
@@ -1539,7 +1540,7 @@
     ret
 }
 
-/// Converts the crate cfg! configuration from String to Symbol.
+/// Converts the crate `cfg!` configuration from `String` to `Symbol`.
 /// `rustc_interface::interface::Config` accepts this in the compiler configuration,
 /// but the symbol interner is not yet set up then, so we must convert it later.
 pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> ast::CrateConfig {
@@ -1550,9 +1551,9 @@
 
 pub fn build_configuration(sess: &Session, mut user_cfg: ast::CrateConfig) -> ast::CrateConfig {
     // Combine the configuration requested by the session (command line) with
-    // some default and generated configuration items
+    // some default and generated configuration items.
     let default_cfg = default_configuration(sess);
-    // If the user wants a test runner, then add the test cfg
+    // If the user wants a test runner, then add the test cfg.
     if sess.opts.test {
         user_cfg.insert((sym::test, None));
     }
@@ -1851,13 +1852,22 @@
     opts
 }
 
-// Convert strings provided as --cfg [cfgspec] into a crate_cfg
+struct NullEmitter;
+
+impl errors::emitter::Emitter for NullEmitter {
+    fn emit_diagnostic(&mut self, _: &errors::DiagnosticBuilder<'_>) {}
+}
+
+// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
 pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
     syntax::with_default_globals(move || {
         let cfg = cfgspecs.into_iter().map(|s| {
-            let sess = parse::ParseSess::new(FilePathMapping::empty());
+
+            let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+            let handler = Handler::with_emitter(false, None, Box::new(NullEmitter));
+            let sess = ParseSess::with_span_handler(handler, cm);
             let filename = FileName::cfg_spec_source_code(&s);
-            let mut parser = parse::new_parser_from_source_str(&sess, filename, s.to_string());
+            let mut parser = new_parser_from_source_str(&sess, filename, s.to_string());
 
             macro_rules! error {($reason: expr) => {
                 early_error(ErrorOutputType::default(),
@@ -1917,7 +1927,7 @@
     (lint_opts, describe_lints, lint_cap)
 }
 
-/// Parse the `--color` flag
+/// Parses the `--color` flag.
 pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
     match matches.opt_str("color").as_ref().map(|s| &s[..]) {
         Some("auto") => ColorConfig::Auto,
@@ -1929,7 +1939,7 @@
         Some(arg) => early_error(
             ErrorOutputType::default(),
             &format!(
-                "argument for --color must be auto, \
+                "argument for `--color` must be auto, \
                  always or never (instead was `{}`)",
                 arg
             ),
@@ -1974,16 +1984,16 @@
     (json_rendered(json_color), json_artifact_notifications)
 }
 
-/// Parse the `--error-format` flag
+/// Parses the `--error-format` flag.
 pub fn parse_error_format(
     matches: &getopts::Matches,
     color: ColorConfig,
     json_rendered: HumanReadableErrorType,
 ) -> ErrorOutputType {
-    // We need the opts_present check because the driver will send us Matches
+    // We need the `opts_present` check because the driver will send us Matches
     // with only stable options if no unstable options are used. Since error-format
-    // is unstable, it will not be present. We have to use opts_present not
-    // opt_present because the latter will panic.
+    // is unstable, it will not be present. We have to use `opts_present` not
+    // `opt_present` because the latter will panic.
     let error_format = if matches.opts_present(&["error-format".to_owned()]) {
         match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
             None |
@@ -1998,7 +2008,7 @@
             Some(arg) => early_error(
                 ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
                 &format!(
-                    "argument for --error-format must be `human`, `json` or \
+                    "argument for `--error-format` must be `human`, `json` or \
                      `short` (instead was `{}`)",
                     arg
                 ),
@@ -2037,7 +2047,7 @@
             early_error(
                 ErrorOutputType::default(),
                 &format!(
-                    "argument for --edition must be one of: \
+                    "argument for `--edition` must be one of: \
                      {}. (instead was `{}`)",
                     EDITION_NAME_LIST,
                     arg
@@ -2051,7 +2061,7 @@
         early_error(
                 ErrorOutputType::default(),
                 &format!(
-                    "Edition {} is unstable and only \
+                    "edition {} is unstable and only \
                      available for nightly builds of rustc.",
                     edition,
                 )
@@ -2075,14 +2085,14 @@
         if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
             early_error(
                 ErrorOutputType::Json { pretty: false, json_rendered },
-                "--error-format=pretty-json is unstable",
+                "`--error-format=pretty-json` is unstable",
             );
         }
         if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) =
             error_format {
             early_error(
                 ErrorOutputType::Json { pretty: false, json_rendered },
-                "--error-format=human-annotate-rs is unstable",
+                "`--error-format=human-annotate-rs` is unstable",
             );
         }
     }
@@ -2116,7 +2126,7 @@
     let mut codegen_units = cg.codegen_units;
     let mut disable_thinlto = false;
 
-    // Issue #30063: if user requests llvm-related output to one
+    // Issue #30063: if user requests LLVM-related output to one
     // particular path, disable codegen-units.
     let incompatible: Vec<_> = output_types
         .iter()
@@ -2132,8 +2142,8 @@
                         early_warn(
                             error_format,
                             &format!(
-                                "--emit={} with -o incompatible with \
-                                 -C codegen-units=N for N > 1",
+                                "`--emit={}` with `-o` incompatible with \
+                                 `-C codegen-units=N` for N > 1",
                                 ot
                             ),
                         );
@@ -2153,21 +2163,21 @@
     if debugging_opts.threads == Some(0) {
         early_error(
             error_format,
-            "Value for threads must be a positive nonzero integer",
+            "value for threads must be a positive non-zero integer",
         );
     }
 
     if debugging_opts.threads.unwrap_or(1) > 1 && debugging_opts.fuel.is_some() {
         early_error(
             error_format,
-            "Optimization fuel is incompatible with multiple threads",
+            "optimization fuel is incompatible with multiple threads",
         );
     }
 
     if codegen_units == Some(0) {
         early_error(
             error_format,
-            "Value for codegen units must be a positive nonzero integer",
+            "value for codegen units must be a positive non-zero integer",
         );
     }
 
@@ -2414,10 +2424,10 @@
         )
     }
 
-    // We start out with a Vec<(Option<String>, bool)>>,
-    // and later convert it into a BTreeSet<(Option<String>, bool)>
+    // 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
+    // 'public' value.
     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))) {
@@ -2616,15 +2626,15 @@
 /// The values of all command-line arguments that are relevant for dependency
 /// tracking are hashed into a single value that determines whether the
 /// incremental compilation cache can be re-used or not. This hashing is done
-/// via the DepTrackingHash trait defined below, since the standard Hash
-/// implementation might not be suitable (e.g., arguments are stored in a Vec,
+/// via the `DepTrackingHash` trait defined below, since the standard `Hash`
+/// implementation might not be suitable (e.g., arguments are stored in a `Vec`,
 /// the hash of which is order dependent, but we might not want the order of
 /// arguments to make a difference for the hash).
 ///
-/// However, since the value provided by Hash::hash often *is* suitable,
+/// However, since the value provided by `Hash::hash` often *is* suitable,
 /// especially for primitive types, there is the
-/// impl_dep_tracking_hash_via_hash!() macro that allows to simply reuse the
-/// Hash implementation for DepTrackingHash. It's important though that
+/// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the
+/// `Hash` implementation for `DepTrackingHash`. It's important though that
 /// we have an opt-in scheme here, so one is hopefully forced to think about
 /// how the hash should be calculated when adding a new command-line argument.
 mod dep_tracking {
@@ -2637,9 +2647,9 @@
     use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
                 Passes, Sanitizer, LtoCli, LinkerPluginLto, SwitchWithOptPath,
                 SymbolManglingVersion};
-    use syntax::feature_gate::UnstableFeatures;
     use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple};
     use syntax::edition::Edition;
+    use syntax::feature_gate::UnstableFeatures;
 
     pub trait DepTrackingHash {
         fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index f01883d..8656ebb 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -79,12 +79,12 @@
     /// if the value stored here has been affected by path remapping.
     pub working_dir: (PathBuf, bool),
 
-    // FIXME: lint_store and buffered_lints are not thread-safe,
-    // but are only used in a single thread
+    // FIXME: `lint_store` and `buffered_lints` are not thread-safe,
+    // but are only used in a single thread.
     pub lint_store: RwLock<lint::LintStore>,
     pub buffered_lints: Lock<Option<lint::LintBuffer>>,
 
-    /// Set of (DiagnosticId, Option<Span>, message) tuples tracking
+    /// Set of `(DiagnosticId, Option<Span>, message)` tuples tracking
     /// (sub)diagnostics that have been set once, but should not be set again,
     /// in order to avoid redundantly verbose output (Issue #24690, #44953).
     pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
@@ -92,11 +92,11 @@
     pub plugin_attributes: Lock<Vec<(Symbol, AttributeType)>>,
     pub crate_types: Once<Vec<config::CrateType>>,
     pub dependency_formats: Once<dependency_format::Dependencies>,
-    /// The crate_disambiguator is constructed out of all the `-C metadata`
+    /// The `crate_disambiguator` is constructed out of all the `-C metadata`
     /// arguments passed to the compiler. Its value together with the crate-name
     /// forms a unique global identifier for the crate. It is used to allow
     /// multiple crates with the same name to coexist. See the
-    /// rustc_codegen_llvm::back::symbol_names module for more information.
+    /// `rustc_codegen_llvm::back::symbol_names` module for more information.
     pub crate_disambiguator: Once<CrateDisambiguator>,
 
     features: Once<feature_gate::Features>,
@@ -111,7 +111,7 @@
     /// The maximum number of stackframes allowed in const eval.
     pub const_eval_stack_frame_limit: usize,
 
-    /// The metadata::creader module may inject an allocator/panic_runtime
+    /// The `metadata::creader` module may inject an allocator/`panic_runtime`
     /// dependency if it didn't already find one, and this tracks what was
     /// injected.
     pub allocator_kind: Once<Option<AllocatorKind>>,
@@ -130,7 +130,7 @@
     /// Used by `-Z profile-queries` in `util::common`.
     pub profile_channel: Lock<Option<mpsc::Sender<ProfileQueriesMsg>>>,
 
-    /// Used by -Z self-profile
+    /// Used by `-Z self-profile`.
     pub self_profiling: Option<Arc<SelfProfiler>>,
 
     /// Some measurements that are being gathered during compilation.
@@ -187,16 +187,16 @@
     pub normalize_projection_ty: AtomicUsize,
 }
 
-/// Enum to support dispatch of one-time diagnostics (in Session.diag_once)
+/// Enum to support dispatch of one-time diagnostics (in `Session.diag_once`).
 enum DiagnosticBuilderMethod {
     Note,
     SpanNote,
     SpanSuggestion(String), // suggestion
-                            // add more variants as needed to support one-time diagnostics
+                            // Add more variants as needed to support one-time diagnostics.
 }
 
-/// Diagnostic message ID—used by `Session.one_time_diagnostics` to avoid
-/// emitting the same message more than once
+/// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid
+/// emitting the same message more than once.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub enum DiagnosticMessageId {
     ErrorId(u16), // EXXXX error code as integer
@@ -408,7 +408,7 @@
             Some(next) => {
                 self.next_node_id.set(ast::NodeId::from_usize(next));
             }
-            None => bug!("Input too large, ran out of node ids!"),
+            None => bug!("input too large; ran out of node-IDs!"),
         }
 
         id
@@ -440,11 +440,11 @@
                     diag_builder.note(message);
                 }
                 DiagnosticBuilderMethod::SpanNote => {
-                    let span = span_maybe.expect("span_note needs a span");
+                    let span = span_maybe.expect("`span_note` needs a span");
                     diag_builder.span_note(span, message);
                 }
                 DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
-                    let span = span_maybe.expect("span_suggestion_* needs a span");
+                    let span = span_maybe.expect("`span_suggestion_*` needs a span");
                     diag_builder.span_suggestion(
                         span,
                         message,
@@ -688,7 +688,7 @@
 
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
         // "mcount" function relies on stack pointer.
-        // See https://sourceware.org/binutils/docs/gprof/Implementation.html
+        // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
         if self.instrument_mcount() {
             true
         } else if let Some(x) = self.opts.cg.force_frame_pointers {
@@ -699,7 +699,7 @@
     }
 
     /// Returns the symbol name for the registrar function,
-    /// given the crate Svh and the function DefIndex.
+    /// given the crate `Svh` and the function `DefIndex`.
     pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String {
         format!(
             "__rustc_plugin_registrar_{}__",
@@ -719,7 +719,7 @@
             &self.sysroot,
             self.opts.target_triple.triple(),
             &self.opts.search_paths,
-            // target_tlib_path==None means it's the same as host_tlib_path.
+            // `target_tlib_path == None` means it's the same as `host_tlib_path`.
             self.target_tlib_path.as_ref().unwrap_or(&self.host_tlib_path),
             kind,
         )
@@ -779,12 +779,12 @@
         if let IncrCompSession::Active { .. } = *incr_comp_session {
         } else {
             bug!(
-                "Trying to finalize IncrCompSession `{:?}`",
+                "trying to finalize `IncrCompSession` `{:?}`",
                 *incr_comp_session
-            )
+            );
         }
 
-        // Note: This will also drop the lock file, thus unlocking the directory
+        // Note: this will also drop the lock file, thus unlocking the directory.
         *incr_comp_session = IncrCompSession::Finalized {
             session_directory: new_directory_path,
         };
@@ -800,13 +800,15 @@
             } => session_directory.clone(),
             IncrCompSession::InvalidBecauseOfErrors { .. } => return,
             _ => bug!(
-                "Trying to invalidate IncrCompSession `{:?}`",
+                "trying to invalidate `IncrCompSession` `{:?}`",
                 *incr_comp_session
             ),
         };
 
-        // Note: This will also drop the lock file, thus unlocking the directory
-        *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { session_directory };
+        // Note: this will also drop the lock file, thus unlocking the directory.
+        *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors {
+            session_directory,
+        };
     }
 
     pub fn incr_comp_session_dir(&self) -> cell::Ref<'_, PathBuf> {
@@ -815,8 +817,8 @@
             incr_comp_session,
             |incr_comp_session| match *incr_comp_session {
                 IncrCompSession::NotInitialized => bug!(
-                    "Trying to get session directory from IncrCompSession `{:?}`",
-                    *incr_comp_session
+                    "trying to get session directory from `IncrCompSession`: {:?}",
+                    *incr_comp_session,
                 ),
                 IncrCompSession::Active {
                     ref session_directory,
@@ -1185,7 +1187,10 @@
     );
     let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
 
-    let p_s = parse::ParseSess::with_span_handler(span_diagnostic, source_map);
+    let parse_sess = parse::ParseSess::with_span_handler(
+        span_diagnostic,
+        source_map,
+    );
     let sysroot = match &sopts.maybe_sysroot {
         Some(sysroot) => sysroot.clone(),
         None => filesearch::get_or_default_sysroot(),
@@ -1214,7 +1219,7 @@
     let print_fuel = AtomicU64::new(0);
 
     let working_dir = env::current_dir().unwrap_or_else(|e|
-        p_s.span_diagnostic
+        parse_sess.span_diagnostic
             .fatal(&format!("Current directory is invalid: {}", e))
             .raise()
     );
@@ -1232,7 +1237,7 @@
         opts: sopts,
         host_tlib_path,
         target_tlib_path,
-        parse_sess: p_s,
+        parse_sess,
         sysroot,
         local_crate_source_file,
         working_dir,
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 93742c8..03cc00d 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -1,20 +1,21 @@
 use super::{
+    ConstEvalFailure,
+    EvaluationResult,
     FulfillmentError,
     FulfillmentErrorCode,
     MismatchedProjectionTypes,
+    ObjectSafetyViolation,
     Obligation,
     ObligationCause,
     ObligationCauseCode,
     OnUnimplementedDirective,
     OnUnimplementedNote,
     OutputTypeParameterMismatch,
-    TraitNotObjectSafe,
-    ConstEvalFailure,
+    Overflow,
     PredicateObligation,
     SelectionContext,
     SelectionError,
-    ObjectSafetyViolation,
-    Overflow,
+    TraitNotObjectSafe,
 };
 
 use crate::hir;
@@ -35,7 +36,7 @@
 use errors::{Applicability, DiagnosticBuilder};
 use std::fmt;
 use syntax::ast;
-use syntax::symbol::sym;
+use syntax::symbol::{sym, kw};
 use syntax_pos::{DUMMY_SP, Span, ExpnKind};
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
@@ -657,19 +658,22 @@
                             span,
                             E0277,
                             "{}",
-                            message.unwrap_or_else(||
-                                format!("the trait bound `{}` is not satisfied{}",
-                                        trait_ref.to_predicate(), post_message)
-                            ));
+                            message.unwrap_or_else(|| format!(
+                                "the trait bound `{}` is not satisfied{}",
+                                trait_ref.to_predicate(),
+                                post_message,
+                            )));
 
                         let explanation =
                             if obligation.cause.code == ObligationCauseCode::MainFunctionType {
                                 "consider using `()`, or a `Result`".to_owned()
                             } else {
-                                format!("{}the trait `{}` is not implemented for `{}`",
-                                        pre_message,
-                                        trait_ref,
-                                        trait_ref.self_ty())
+                                format!(
+                                    "{}the trait `{}` is not implemented for `{}`",
+                                    pre_message,
+                                    trait_ref,
+                                    trait_ref.self_ty(),
+                                )
                             };
 
                         if let Some(ref s) = label {
@@ -686,6 +690,7 @@
                         }
 
                         self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
+                        self.suggest_fn_call(&obligation, &mut err, &trait_ref);
                         self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
                         self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
 
@@ -953,6 +958,57 @@
         }
     }
 
+    fn suggest_fn_call(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) {
+        let self_ty = trait_ref.self_ty();
+        match self_ty.sty {
+            ty::FnDef(def_id, _) => {
+                // We tried to apply the bound to an `fn`. Check whether calling it would evaluate
+                // to a type that *would* satisfy the trait binding. If it would, suggest calling
+                // it: `bar(foo)` -> `bar(foo)`. This case is *very* likely to be hit if `foo` is
+                // `async`.
+                let output_ty = self_ty.fn_sig(self.tcx).output();
+                let new_trait_ref = ty::TraitRef {
+                    def_id: trait_ref.def_id(),
+                    substs: self.tcx.mk_substs_trait(output_ty.skip_binder(), &[]),
+                };
+                let obligation = Obligation::new(
+                    obligation.cause.clone(),
+                    obligation.param_env,
+                    new_trait_ref.to_predicate(),
+                );
+                match self.evaluate_obligation(&obligation) {
+                    Ok(EvaluationResult::EvaluatedToOk) |
+                    Ok(EvaluationResult::EvaluatedToOkModuloRegions) |
+                    Ok(EvaluationResult::EvaluatedToAmbig) => {
+                        if let Some(hir::Node::Item(hir::Item {
+                            ident,
+                            node: hir::ItemKind::Fn(.., body_id),
+                            ..
+                        })) = self.tcx.hir().get_if_local(def_id) {
+                            let body = self.tcx.hir().body(*body_id);
+                            err.help(&format!(
+                                "use parentheses to call the function: `{}({})`",
+                                ident,
+                                body.params.iter()
+                                    .map(|arg| match &arg.pat.node {
+                                        hir::PatKind::Binding(_, _, ident, None)
+                                        if ident.name != kw::SelfLower => ident.to_string(),
+                                        _ => "_".to_string(),
+                                    }).collect::<Vec<_>>().join(", ")));
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+    }
+
     /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
     /// suggest removing these references until we reach a type that implements the trait.
     fn suggest_remove_reference(
@@ -1328,7 +1384,10 @@
         let mut reported_violations = FxHashSet::default();
         for violation in violations {
             if reported_violations.insert(violation.clone()) {
-                err.note(&violation.error_msg());
+                match violation.span() {
+                    Some(span) => err.span_label(span, violation.error_msg()),
+                    None => err.note(&violation.error_msg()),
+                };
             }
         }
         Some(err)
@@ -1535,17 +1594,23 @@
                 err.note("only the last element of a tuple may have a dynamically sized type");
             }
             ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{}` is well-formed",
-                                  data));
+                err.note(&format!(
+                    "required so that the projection `{}` is well-formed",
+                    data,
+                ));
             }
             ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
-                err.note(&format!("required so that reference `{}` does not outlive its referent",
-                                  ref_ty));
+                err.note(&format!(
+                    "required so that reference `{}` does not outlive its referent",
+                    ref_ty,
+                ));
             }
             ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
-                err.note(&format!("required so that the lifetime bound of `{}` for `{}` \
-                                   is satisfied",
-                                  region, object_ty));
+                err.note(&format!(
+                    "required so that the lifetime bound of `{}` for `{}` is satisfied",
+                    region,
+                    object_ty,
+                ));
             }
             ObligationCauseCode::ItemObligation(item_def_id) => {
                 let item_name = tcx.def_path_str(item_def_id);
@@ -1553,7 +1618,7 @@
 
                 if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
                     let sp = tcx.sess.source_map().def_span(sp);
-                    err.span_note(sp, &msg);
+                    err.span_label(sp, &msg);
                 } else {
                     err.note(&msg);
                 }
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index c1de493..4494c03 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -68,6 +68,10 @@
     pub stalled_on: Vec<Ty<'tcx>>,
 }
 
+// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(PendingPredicateObligation<'_>, 136);
+
 impl<'a, 'tcx> FulfillmentContext<'tcx> {
     /// Creates a new fulfillment context.
     pub fn new() -> FulfillmentContext<'tcx> {
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 1ca92d7..d268309 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -123,6 +123,10 @@
 pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
 pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
 
+// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(PredicateObligation<'_>, 112);
+
 /// The reason why we incurred this obligation; used for error reporting.
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct ObligationCause<'tcx> {
@@ -147,7 +151,8 @@
             ObligationCauseCode::StartFunctionType => {
                 tcx.sess.source_map().def_span(self.span)
             }
-            ObligationCauseCode::MatchExpressionArm { arm_span, .. } => arm_span,
+            ObligationCauseCode::MatchExpressionArm(
+                box MatchExpressionArmCause { arm_span, .. }) => arm_span,
             _ => self.span,
         }
     }
@@ -223,23 +228,13 @@
     ExprAssignable,
 
     /// Computing common supertype in the arms of a match expression
-    MatchExpressionArm {
-        arm_span: Span,
-        source: hir::MatchSource,
-        prior_arms: Vec<Span>,
-        last_ty: Ty<'tcx>,
-        discrim_hir_id: hir::HirId,
-    },
+    MatchExpressionArm(Box<MatchExpressionArmCause<'tcx>>),
 
     /// Computing common supertype in the pattern guard for the arms of a match expression
     MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> },
 
     /// Computing common supertype in an if expression
-    IfExpression {
-        then: Span,
-        outer: Option<Span>,
-        semicolon: Option<Span>,
-    },
+    IfExpression(Box<IfExpressionCause>),
 
     /// Computing common supertype of an if expression with no else counter-part
     IfExpressionWithNoElse,
@@ -269,6 +264,26 @@
     TrivialBound,
 }
 
+// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(ObligationCauseCode<'_>, 32);
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct MatchExpressionArmCause<'tcx> {
+    pub arm_span: Span,
+    pub source: hir::MatchSource,
+    pub prior_arms: Vec<Span>,
+    pub last_ty: Ty<'tcx>,
+    pub discrim_hir_id: hir::HirId,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct IfExpressionCause {
+    pub then: Span,
+    pub outer: Option<Span>,
+    pub semicolon: Option<Span>,
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct DerivedObligationCause<'tcx> {
     /// The trait reference of the parent obligation that led to the
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 7ea7bf0..a7990c4 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -20,7 +20,7 @@
 use std::iter::{self};
 use syntax::ast::{self};
 use syntax::symbol::InternedString;
-use syntax_pos::Span;
+use syntax_pos::{Span, DUMMY_SP};
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum ObjectSafetyViolation {
@@ -32,10 +32,10 @@
     SupertraitSelf,
 
     /// Method has something illegal.
-    Method(ast::Name, MethodViolationCode),
+    Method(ast::Name, MethodViolationCode, Span),
 
     /// Associated const.
-    AssocConst(ast::Name),
+    AssocConst(ast::Name, Span),
 }
 
 impl ObjectSafetyViolation {
@@ -46,22 +46,35 @@
             ObjectSafetyViolation::SupertraitSelf =>
                 "the trait cannot use `Self` as a type parameter \
                  in the supertraits or where-clauses".into(),
-            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) =>
-                format!("method `{}` has no receiver", name).into(),
-            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) =>
-                format!("method `{}` references the `Self` type \
-                         in its arguments or return type", name).into(),
-            ObjectSafetyViolation::Method(name,
-                                            MethodViolationCode::WhereClauseReferencesSelf(_)) =>
-                format!("method `{}` references the `Self` type in where clauses", name).into(),
-            ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
+            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) =>
+                format!("associated function `{}` has no `self` parameter", name).into(),
+            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!(
+                "method `{}` references the `Self` type in its parameters or return type",
+                name,
+            ).into(),
+            ObjectSafetyViolation::Method(
+                name,
+                MethodViolationCode::WhereClauseReferencesSelf,
+                _,
+            ) => format!("method `{}` references the `Self` type in where clauses", name).into(),
+            ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) =>
                 format!("method `{}` has generic type parameters", name).into(),
-            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) =>
-                format!("method `{}`'s receiver cannot be dispatched on", name).into(),
-            ObjectSafetyViolation::AssocConst(name) =>
+            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) =>
+                format!("method `{}`'s `self` parameter cannot be dispatched on", name).into(),
+            ObjectSafetyViolation::AssocConst(name, _) =>
                 format!("the trait cannot contain associated consts like `{}`", name).into(),
         }
     }
+
+    pub fn span(&self) -> Option<Span> {
+        // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
+        // diagnostics use a `note` instead of a `span_label`.
+        match *self {
+            ObjectSafetyViolation::AssocConst(_, span) |
+            ObjectSafetyViolation::Method(_, _, span) if span != DUMMY_SP => Some(span),
+            _ => None,
+        }
+    }
 }
 
 /// Reasons a method might not be object-safe.
@@ -74,7 +87,7 @@
     ReferencesSelf,
 
     /// e.g., `fn foo(&self) where Self: Clone`
-    WhereClauseReferencesSelf(Span),
+    WhereClauseReferencesSelf,
 
     /// e.g., `fn foo<A>()`
     Generic,
@@ -88,9 +101,10 @@
     /// astconv -- currently, `Self` in supertraits. This is needed
     /// because `object_safety_violations` can't be used during
     /// type collection.
-    pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
-                                            -> Vec<ObjectSafetyViolation>
-    {
+    pub fn astconv_object_safety_violations(
+        self,
+        trait_def_id: DefId,
+    ) -> Vec<ObjectSafetyViolation> {
         debug_assert!(self.generics_of(trait_def_id).has_self);
         let violations = traits::supertrait_def_ids(self, trait_def_id)
             .filter(|&def_id| self.predicates_reference_self(def_id, true))
@@ -116,19 +130,19 @@
     }
 
     /// We say a method is *vtable safe* if it can be invoked on a trait
-    /// object.  Note that object-safe traits can have some
-    /// non-vtable-safe methods, so long as they require `Self:Sized` or
-    /// otherwise ensure that they cannot be used when `Self=Trait`.
+    /// object. Note that object-safe traits can have some
+    /// non-vtable-safe methods, so long as they require `Self: Sized` or
+    /// otherwise ensure that they cannot be used when `Self = Trait`.
     pub fn is_vtable_safe_method(self, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
         debug_assert!(self.generics_of(trait_def_id).has_self);
         debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
-        // Any method that has a `Self : Sized` requisite can't be called.
+        // Any method that has a `Self: Sized` bound cannot be called.
         if self.generics_require_sized_self(method.def_id) {
             return false;
         }
 
         match self.virtual_call_violation_for_method(trait_def_id, method) {
-            None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
+            None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
             Some(_) => false,
         }
     }
@@ -138,12 +152,15 @@
         let mut violations: Vec<_> = self.associated_items(trait_def_id)
             .filter(|item| item.kind == ty::AssocKind::Method)
             .filter_map(|item|
-                self.object_safety_violation_for_method(trait_def_id, &item)
-                    .map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
+                self.object_safety_violation_for_method(trait_def_id, &item).map(|code| {
+                    ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span)
+                })
             ).filter(|violation| {
-                if let ObjectSafetyViolation::Method(_,
-                    MethodViolationCode::WhereClauseReferencesSelf(span)) = violation
-                {
+                if let ObjectSafetyViolation::Method(
+                    _,
+                    MethodViolationCode::WhereClauseReferencesSelf,
+                    span,
+                ) = violation {
                     // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
                     // It's also hard to get a use site span, so we use the method definition span.
                     self.lint_node_note(
@@ -169,7 +186,7 @@
 
         violations.extend(self.associated_items(trait_def_id)
             .filter(|item| item.kind == ty::AssocKind::Const)
-            .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name)));
+            .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)));
 
         debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
                trait_def_id,
@@ -325,8 +342,7 @@
                 .visit_tys_shallow(|t| {
                     self.contains_illegal_self_type_reference(trait_def_id, t)
                 }) {
-            let span = self.def_span(method.def_id);
-            return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
+            return Some(MethodViolationCode::WhereClauseReferencesSelf);
         }
 
         let receiver_ty = self.liberate_late_bound_regions(
@@ -334,15 +350,15 @@
             &sig.map_bound(|sig| sig.inputs()[0]),
         );
 
-        // until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
+        // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
         // However, this is already considered object-safe. We allow it as a special case here.
         // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
-        // `Receiver: Unsize<Receiver[Self => dyn Trait]>`
+        // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
         if receiver_ty != self.types.self_param {
             if !self.receiver_is_dispatchable(method, receiver_ty) {
                 return Some(MethodViolationCode::UndispatchableReceiver);
             } else {
-                // sanity check to make sure the receiver actually has the layout of a pointer
+                // Do sanity check to make sure the receiver actually has the layout of a pointer.
 
                 use crate::ty::layout::Abi;
 
@@ -352,12 +368,12 @@
                     match self.layout_of(param_env.and(ty)) {
                         Ok(layout) => &layout.abi,
                         Err(err) => bug!(
-                            "Error: {}\n while computing layout for type {:?}", err, ty
+                            "error: {}\n while computing layout for type {:?}", err, ty
                         )
                     }
                 };
 
-                // e.g., Rc<()>
+                // e.g., `Rc<()>`
                 let unit_receiver_ty = self.receiver_for_self_ty(
                     receiver_ty, self.mk_unit(), method.def_id
                 );
@@ -368,7 +384,7 @@
                         self.sess.delay_span_bug(
                             self.def_span(method.def_id),
                             &format!(
-                                "Receiver when Self = () should have a Scalar ABI, found {:?}",
+                                "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
                                 abi
                             ),
                         );
@@ -379,7 +395,7 @@
                     trait_def_id, self.mk_region(ty::ReStatic)
                 );
 
-                // e.g., Rc<dyn Trait>
+                // e.g., `Rc<dyn Trait>`
                 let trait_object_receiver = self.receiver_for_self_ty(
                     receiver_ty, trait_object_ty, method.def_id
                 );
@@ -390,7 +406,8 @@
                         self.sess.delay_span_bug(
                             self.def_span(method.def_id),
                             &format!(
-                                "Receiver when Self = {} should have a ScalarPair ABI, found {:?}",
+                                "receiver when `Self = {}` should have a ScalarPair ABI; \
+                                 found {:?}",
                                 trait_object_ty, abi
                             ),
                         );
@@ -402,8 +419,8 @@
         None
     }
 
-    /// Performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
-    /// e.g., for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`.
+    /// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`.
+    /// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
     fn receiver_for_self_ty(
         self,
         receiver_ty: Ty<'tcx>,
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 0a42b6b..5a988d9 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -9,10 +9,9 @@
 use syntax::attr;
 use syntax::symbol::{Symbol, kw, sym};
 use syntax_pos::Span;
-use syntax_pos::symbol::LocalInternedString;
 
 #[derive(Clone, Debug)]
-pub struct OnUnimplementedFormatString(LocalInternedString);
+pub struct OnUnimplementedFormatString(Symbol);
 
 #[derive(Debug)]
 pub struct OnUnimplementedDirective {
@@ -89,19 +88,19 @@
             if item.check_name(sym::message) && message.is_none() {
                 if let Some(message_) = item.value_str() {
                     message = Some(OnUnimplementedFormatString::try_parse(
-                        tcx, trait_def_id, message_.as_str(), span)?);
+                        tcx, trait_def_id, message_, span)?);
                     continue;
                 }
             } else if item.check_name(sym::label) && label.is_none() {
                 if let Some(label_) = item.value_str() {
                     label = Some(OnUnimplementedFormatString::try_parse(
-                        tcx, trait_def_id, label_.as_str(), span)?);
+                        tcx, trait_def_id, label_, span)?);
                     continue;
                 }
             } else if item.check_name(sym::note) && note.is_none() {
                 if let Some(note_) = item.value_str() {
                     note = Some(OnUnimplementedFormatString::try_parse(
-                        tcx, trait_def_id, note_.as_str(), span)?);
+                        tcx, trait_def_id, note_, span)?);
                     continue;
                 }
             } else if item.check_name(sym::on) && is_root &&
@@ -154,7 +153,7 @@
                 message: None,
                 subcommands: vec![],
                 label: Some(OnUnimplementedFormatString::try_parse(
-                    tcx, trait_def_id, value.as_str(), attr.span)?),
+                    tcx, trait_def_id, value, attr.span)?),
                 note: None,
             }))
         } else {
@@ -218,7 +217,7 @@
     fn try_parse(
         tcx: TyCtxt<'tcx>,
         trait_def_id: DefId,
-        from: LocalInternedString,
+        from: Symbol,
         err_sp: Span,
     ) -> Result<Self, ErrorReported> {
         let result = OnUnimplementedFormatString(from);
@@ -234,7 +233,8 @@
     ) -> Result<(), ErrorReported> {
         let name = tcx.item_name(trait_def_id);
         let generics = tcx.generics_of(trait_def_id);
-        let parser = Parser::new(&self.0, None, vec![], false);
+        let s = self.0.as_str();
+        let parser = Parser::new(&s, None, vec![], false);
         let mut result = Ok(());
         for token in parser {
             match token {
@@ -294,7 +294,8 @@
         }).collect::<FxHashMap<Symbol, String>>();
         let empty_string = String::new();
 
-        let parser = Parser::new(&self.0, None, vec![], false);
+        let s = self.0.as_str();
+        let parser = Parser::new(&s, None, vec![], false);
         parser.map(|p|
             match p {
                 Piece::String(s) => s,
diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs
index 2ee6364..b9557ce 100644
--- a/src/librustc/traits/query/evaluate_obligation.rs
+++ b/src/librustc/traits/query/evaluate_obligation.rs
@@ -1,7 +1,8 @@
 use crate::infer::InferCtxt;
 use crate::infer::canonical::OriginalQueryValues;
-use crate::traits::{EvaluationResult, PredicateObligation, SelectionContext,
-             TraitQueryMode, OverflowError};
+use crate::traits::{
+    EvaluationResult, PredicateObligation, SelectionContext, TraitQueryMode, OverflowError,
+};
 
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// Evaluates whether the predicate can be satisfied (by any means)
diff --git a/src/librustc/traits/query/method_autoderef.rs b/src/librustc/traits/query/method_autoderef.rs
index 6b9bdfd..039dea1 100644
--- a/src/librustc/traits/query/method_autoderef.rs
+++ b/src/librustc/traits/query/method_autoderef.rs
@@ -6,11 +6,11 @@
 pub struct CandidateStep<'tcx> {
     pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
     pub autoderefs: usize,
-    // true if the type results from a dereference of a raw pointer.
-    // when assembling candidates, we include these steps, but not when
-    // picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
-    // `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
-    // `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
+    /// `true` if the type results from a dereference of a raw pointer.
+    /// when assembling candidates, we include these steps, but not when
+    /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
+    /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
+    /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
     pub from_unsafe_deref: bool,
     pub unsize: bool,
 }
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 05b698e..6930c93 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -508,31 +508,33 @@
                 trait_item_def_id,
             }),
             super::ExprAssignable => Some(super::ExprAssignable),
-            super::MatchExpressionArm {
+            super::MatchExpressionArm(box super::MatchExpressionArmCause {
                 arm_span,
                 source,
                 ref prior_arms,
                 last_ty,
                 discrim_hir_id,
-            } => {
+            }) => {
                 tcx.lift(&last_ty).map(|last_ty| {
-                    super::MatchExpressionArm {
+                    super::MatchExpressionArm(box super::MatchExpressionArmCause {
                         arm_span,
                         source,
                         prior_arms: prior_arms.clone(),
                         last_ty,
                         discrim_hir_id,
-                    }
+                    })
                 })
             }
             super::MatchExpressionArmPattern { span, ty } => {
                 tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
             }
-            super::IfExpression { then, outer, semicolon } => Some(super::IfExpression {
-                then,
-                outer,
-                semicolon,
-            }),
+            super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
+                Some(super::IfExpression(box super::IfExpressionCause {
+                    then,
+                    outer,
+                    semicolon,
+                }))
+            }
             super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
             super::MainFunctionType => Some(super::MainFunctionType),
             super::StartFunctionType => Some(super::StartFunctionType),
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 07d6f63..3d36790 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -512,7 +512,7 @@
     (impl_trait_ref, impl_obligations)
 }
 
-/// See `super::obligations_for_generics`
+/// See [`super::obligations_for_generics`].
 pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
                                      recursion_depth: usize,
                                      param_env: ty::ParamEnv<'tcx>,
@@ -562,7 +562,7 @@
         predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
     }
 
-    /// Cast a trait reference into a reference to one of its super
+    /// Casts a trait reference into a reference to one of its super
     /// traits; returns `None` if `target_trait_def_id` is not a
     /// supertrait.
     pub fn upcast_choices(self,
@@ -571,7 +571,7 @@
                           -> Vec<ty::PolyTraitRef<'tcx>>
     {
         if source_trait_ref.def_id() == target_trait_def_id {
-            return vec![source_trait_ref]; // shorcut the most common case
+            return vec![source_trait_ref]; // Shortcut the most common case.
         }
 
         supertraits(self, source_trait_ref)
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
index 1ddc678..1aa2150 100644
--- a/src/librustc/ty/codec.rs
+++ b/src/librustc/ty/codec.rs
@@ -284,9 +284,11 @@
 #[macro_export]
 macro_rules! __impl_decoder_methods {
     ($($name:ident -> $ty:ty;)*) => {
-        $(fn $name(&mut self) -> Result<$ty, Self::Error> {
-            self.opaque.$name()
-        })*
+        $(
+            fn $name(&mut self) -> Result<$ty, Self::Error> {
+                self.opaque.$name()
+            }
+        )*
     }
 }
 
@@ -327,14 +329,17 @@
 macro_rules! implement_ty_decoder {
     ($DecoderName:ident <$($typaram:tt),*>) => {
         mod __ty_decoder_impl {
-            use super::$DecoderName;
+            use std::borrow::Cow;
+
+            use rustc_serialize::{Decoder, SpecializedDecoder};
+
             use $crate::infer::canonical::CanonicalVarInfos;
             use $crate::ty;
             use $crate::ty::codec::*;
             use $crate::ty::subst::SubstsRef;
             use $crate::hir::def_id::{CrateNum};
-            use rustc_serialize::{Decoder, SpecializedDecoder};
-            use std::borrow::Cow;
+
+            use super::$DecoderName;
 
             impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
                 type Error = String;
@@ -368,8 +373,8 @@
                 }
             }
 
-            // FIXME(#36588) These impls are horribly unsound as they allow
-            // the caller to pick any lifetime for 'tcx, including 'static,
+            // FIXME(#36588): These impls are horribly unsound as they allow
+            // the caller to pick any lifetime for `'tcx`, including `'static`,
             // by using the unspecialized proxies to them.
 
             arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index e240e0d..0155803 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -7,7 +7,7 @@
 use crate::session::config::{BorrowckMode, OutputFilenames};
 use crate::session::config::CrateType;
 use crate::middle;
-use crate::hir::{TraitCandidate, HirId, ItemKind, ItemLocalId, Node};
+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};
 use crate::hir::map as hir_map;
@@ -45,15 +45,16 @@
 use crate::util::common::ErrorReported;
 use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet};
 use crate::util::nodemap::{FxHashMap, FxHashSet};
+
 use errors::DiagnosticBuilder;
-use smallvec::SmallVec;
-use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
-                                           StableHasher, StableHasherResult,
-                                           StableVec};
 use arena::SyncDroplessArena;
+use smallvec::SmallVec;
+use rustc_data_structures::stable_hasher::{
+    HashStable, StableHasher, StableHasherResult, StableVec, hash_stable_hashmap,
+};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal};
 use rustc_data_structures::sharded::ShardedHashMap;
+use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal};
 use std::any::Any;
 use std::borrow::Borrow;
 use std::cmp::Ordering;
@@ -74,8 +75,6 @@
 use syntax::symbol::{Symbol, InternedString, kw, sym};
 use syntax_pos::Span;
 
-use crate::hir;
-
 pub struct AllArenas {
     pub interner: SyncDroplessArena,
 }
@@ -91,10 +90,10 @@
 type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>;
 
 pub struct CtxtInterners<'tcx> {
-    /// The arena that types, regions, etc are allocated from
+    /// The arena that types, regions, etc. are allocated from.
     arena: &'tcx SyncDroplessArena,
 
-    /// Specifically use a speedy hash algorithm for these hash sets,
+    /// Specifically use a speedy hash algorithm for these hash sets, since
     /// they're accessed quite often.
     type_: InternedSet<'tcx, TyS<'tcx>>,
     type_list: InternedSet<'tcx, List<Ty<'tcx>>>,
@@ -129,7 +128,7 @@
         }
     }
 
-    /// Intern a type
+    /// Interns a type.
     #[allow(rustc::usage_of_ty_tykind)]
     #[inline(never)]
     fn intern_ty(&self,
@@ -144,7 +143,6 @@
                 outer_exclusive_binder: flags.outer_exclusive_binder,
             };
 
-
             Interned(self.arena.alloc(ty_struct))
         }).0
     }
@@ -207,26 +205,24 @@
 fn validate_hir_id_for_typeck_tables(local_id_root: Option<DefId>,
                                      hir_id: hir::HirId,
                                      mut_access: bool) {
-    if cfg!(debug_assertions) {
-        if let Some(local_id_root) = local_id_root {
-            if hir_id.owner != local_id_root.index {
-                ty::tls::with(|tcx| {
-                    bug!("node {} with HirId::owner {:?} cannot be placed in \
-                          TypeckTables with local_id_root {:?}",
-                         tcx.hir().node_to_string(hir_id),
-                         DefId::local(hir_id.owner),
-                         local_id_root)
-                });
-            }
-        } else {
-            // We use "Null Object" TypeckTables in some of the analysis passes.
-            // These are just expected to be empty and their `local_id_root` is
-            // `None`. Therefore we cannot verify whether a given `HirId` would
-            // be a valid key for the given table. Instead we make sure that
-            // nobody tries to write to such a Null Object table.
-            if mut_access {
-                bug!("access to invalid TypeckTables")
-            }
+    if let Some(local_id_root) = local_id_root {
+        if hir_id.owner != local_id_root.index {
+            ty::tls::with(|tcx| {
+                bug!("node {} with HirId::owner {:?} cannot be placed in \
+                        TypeckTables with local_id_root {:?}",
+                        tcx.hir().node_to_string(hir_id),
+                        DefId::local(hir_id.owner),
+                        local_id_root)
+            });
+        }
+    } else {
+        // We use "Null Object" TypeckTables in some of the analysis passes.
+        // These are just expected to be empty and their `local_id_root` is
+        // `None`. Therefore we cannot verify whether a given `HirId` would
+        // be a valid key for the given table. Instead we make sure that
+        // nobody tries to write to such a Null Object table.
+        if mut_access {
+            bug!("access to invalid TypeckTables")
         }
     }
 }
@@ -1025,7 +1021,7 @@
 
     hir_map: hir_map::Map<'tcx>,
 
-    /// A map from DefPathHash -> DefId. Includes DefIds from the local crate
+    /// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate
     /// as well as all upstream crates. Only populated in incremental mode.
     pub def_path_hash_to_def_id: Option<FxHashMap<DefPathHash, DefId>>,
 
@@ -1124,9 +1120,9 @@
         })
     }
 
-    /// Allocates a byte or string literal for `mir::interpret`, read-only
+    /// Allocates a read-only byte or string literal for `mir::interpret`.
     pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
-        // create an allocation that just contains these bytes
+        // Create an allocation that just contains these bytes.
         let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
         let alloc = self.intern_const_alloc(alloc);
         self.alloc_map.lock().create_memory_alloc(alloc)
@@ -1346,7 +1342,7 @@
     }
 
     /// Converts a `DefId` into its fully expanded `DefPath` (every
-    /// `DefId` is really just an interned def-path).
+    /// `DefId` is really just an interned `DefPath`).
     ///
     /// Note that if `id` is not local to this crate, the result will
     ///  be a non-local `DefPath`.
@@ -1402,6 +1398,10 @@
         self.cstore.metadata_encoding_version().to_vec()
     }
 
+    pub fn encode_metadata(self)-> EncodedMetadata {
+        self.cstore.encode_metadata(self)
+    }
+
     // Note that this is *untracked* and should only be used within the query
     // system if the result is otherwise tracked through queries
     pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc<dyn Any> {
@@ -1446,25 +1446,25 @@
         self.queries.on_disk_cache.serialize(self.global_tcx(), encoder)
     }
 
-    /// If true, we should use the AST-based borrowck (we may *also* use
+    /// If `true`, we should use the AST-based borrowck (we may *also* use
     /// the MIR-based borrowck).
     pub fn use_ast_borrowck(self) -> bool {
         self.borrowck_mode().use_ast()
     }
 
-    /// If true, we should use the MIR-based borrow check, but also
-    /// fall back on the AST borrow check if the MIR-based one errors.
+    /// If `true`, we should use the MIR-based borrowck, but also
+    /// fall back on the AST borrowck if the MIR-based one errors.
     pub fn migrate_borrowck(self) -> bool {
         self.borrowck_mode().migrate()
     }
 
-    /// If true, make MIR codegen for `match` emit a temp that holds a
+    /// If `true`, make MIR codegen for `match` emit a temp that holds a
     /// borrow of the input to the match expression.
     pub fn generate_borrow_of_any_match_input(&self) -> bool {
         self.emit_read_for_match()
     }
 
-    /// If true, make MIR codegen for `match` emit FakeRead
+    /// If `true`, make MIR codegen for `match` emit FakeRead
     /// statements (which simulate the maximal effect of executing the
     /// patterns in a match arm).
     pub fn emit_read_for_match(&self) -> bool {
@@ -1517,7 +1517,7 @@
         })
     }
 
-    // This method returns the DefId and the BoundRegion corresponding to the given region.
+    // Returns the `DefId` and the `BoundRegion` corresponding to the given region.
     pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
         let (suitable_region_binding_scope, bound_region) = match *region {
             ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
@@ -1550,18 +1550,18 @@
         &self,
         scope_def_id: DefId,
     ) -> Option<Ty<'tcx>> {
-        // HACK: `type_of_def_id()` will fail on these (#55796), so return None
+        // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`.
         let hir_id = self.hir().as_local_hir_id(scope_def_id).unwrap();
         match self.hir().get(hir_id) {
             Node::Item(item) => {
                 match item.node {
-                    ItemKind::Fn(..) => { /* type_of_def_id() will work */ }
+                    ItemKind::Fn(..) => { /* `type_of_def_id()` will work */ }
                     _ => {
                         return None;
                     }
                 }
             }
-            _ => { /* type_of_def_id() will work or panic */ }
+            _ => { /* `type_of_def_id()` will work or panic */ }
         }
 
         let ret_ty = self.type_of(scope_def_id);
@@ -1579,7 +1579,7 @@
         }
     }
 
-    // Here we check if the bound region is in Impl Item.
+    // Checks if the bound region is in Impl Item.
     pub fn is_bound_region_in_impl_item(
         &self,
         suitable_region_binding_scope: DefId,
@@ -1599,23 +1599,15 @@
         false
     }
 
-    /// Determine whether identifiers in the assembly have strict naming rules.
+    /// Determines whether identifiers in the assembly have strict naming rules.
     /// Currently, only NVPTX* targets need it.
     pub fn has_strict_asm_symbol_naming(&self) -> bool {
-        self.gcx.sess.target.target.arch.contains("nvptx")
-    }
-}
-
-impl<'tcx> TyCtxt<'tcx> {
-    pub fn encode_metadata(self)
-        -> EncodedMetadata
-    {
-        self.cstore.encode_metadata(self)
+        self.sess.target.target.arch.contains("nvptx")
     }
 }
 
 impl<'tcx> GlobalCtxt<'tcx> {
-    /// Call the closure with a local `TyCtxt` using the given arena.
+    /// Calls the closure with a local `TyCtxt` using the given arena.
     /// `interners` is a slot passed so we can create a CtxtInterners
     /// with the same lifetime as `arena`.
     pub fn enter_local<F, R>(&'tcx self, f: F) -> R
@@ -1651,7 +1643,7 @@
 /// It would be more efficient if `TypedArena` provided a way to
 /// determine whether the address is in the allocated range.
 ///
-/// None is returned if the value or one of the components is not part
+/// `None` is returned if the value or one of the components is not part
 /// of the provided context.
 /// For `Ty`, `None` can be returned if either the type interner doesn't
 /// contain the `TyKind` key or if the address of the interned
@@ -1662,7 +1654,6 @@
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>;
 }
 
-
 macro_rules! nop_lift {
     ($ty:ty => $lifted:ty) => {
         impl<'a, 'tcx> Lift<'tcx> for $ty {
@@ -1709,7 +1700,7 @@
 nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo}
 nop_list_lift!{ProjectionKind => ProjectionKind}
 
-// this is the impl for `&'a InternalSubsts<'a>`
+// This is the impl for `&'a InternalSubsts<'a>`.
 nop_list_lift!{Kind<'a> => Kind<'tcx>}
 
 pub mod tls {
@@ -1732,43 +1723,43 @@
     use rustc_rayon_core as rayon_core;
 
     /// This is the implicit state of rustc. It contains the current
-    /// TyCtxt and query. It is updated when creating a local interner or
-    /// executing a new query. Whenever there's a TyCtxt value available
-    /// you should also have access to an ImplicitCtxt through the functions
+    /// `TyCtxt` and query. It is updated when creating a local interner or
+    /// executing a new query. Whenever there's a `TyCtxt` value available
+    /// you should also have access to an `ImplicitCtxt` through the functions
     /// in this module.
     #[derive(Clone)]
     pub struct ImplicitCtxt<'a, 'tcx> {
-        /// The current TyCtxt. Initially created by `enter_global` and updated
-        /// by `enter_local` with a new local interner
+        /// The current `TyCtxt`. Initially created by `enter_global` and updated
+        /// by `enter_local` with a new local interner.
         pub tcx: TyCtxt<'tcx>,
 
-        /// The current query job, if any. This is updated by JobOwner::start in
-        /// ty::query::plumbing when executing a query
+        /// The current query job, if any. This is updated by `JobOwner::start` in
+        /// `ty::query::plumbing` when executing a query.
         pub query: Option<Lrc<query::QueryJob<'tcx>>>,
 
         /// Where to store diagnostics for the current query job, if any.
-        /// This is updated by JobOwner::start in ty::query::plumbing when executing a query
+        /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
         pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,
 
         /// Used to prevent layout from recursing too deeply.
         pub layout_depth: usize,
 
         /// The current dep graph task. This is used to add dependencies to queries
-        /// when executing them
+        /// when executing them.
         pub task_deps: Option<&'a Lock<TaskDeps>>,
     }
 
-    /// Sets Rayon's thread local variable which is preserved for Rayon jobs
+    /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
     /// to `value` during the call to `f`. It is restored to its previous value after.
-    /// This is used to set the pointer to the new ImplicitCtxt.
+    /// This is used to set the pointer to the new `ImplicitCtxt`.
     #[cfg(parallel_compiler)]
     #[inline]
     fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
         rayon_core::tlv::with(value, f)
     }
 
-    /// Gets Rayon's thread local variable which is preserved for Rayon jobs.
-    /// This is used to get the pointer to the current ImplicitCtxt.
+    /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
+    /// This is used to get the pointer to the current `ImplicitCtxt`.
     #[cfg(parallel_compiler)]
     #[inline]
     fn get_tlv() -> usize {
@@ -1777,13 +1768,13 @@
 
     #[cfg(not(parallel_compiler))]
     thread_local! {
-        /// A thread local variable which stores a pointer to the current ImplicitCtxt.
+        /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
         static TLV: Cell<usize> = Cell::new(0);
     }
 
     /// Sets TLV to `value` during the call to `f`.
     /// It is restored to its previous value after.
-    /// This is used to set the pointer to the new ImplicitCtxt.
+    /// This is used to set the pointer to the new `ImplicitCtxt`.
     #[cfg(not(parallel_compiler))]
     #[inline]
     fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
@@ -1793,14 +1784,14 @@
         f()
     }
 
-    /// This is used to get the pointer to the current ImplicitCtxt.
+    /// Gets the pointer to the current `ImplicitCtxt`.
     #[cfg(not(parallel_compiler))]
     fn get_tlv() -> usize {
         TLV.with(|tlv| tlv.get())
     }
 
     /// This is a callback from libsyntax as it cannot access the implicit state
-    /// in librustc otherwise
+    /// in librustc otherwise.
     fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         with_opt(|tcx| {
             if let Some(tcx) = tcx {
@@ -1825,7 +1816,7 @@
         })
     }
 
-    /// Sets up the callbacks from libsyntax on the current thread
+    /// Sets up the callbacks from libsyntax on the current thread.
     pub fn with_thread_locals<F, R>(f: F) -> R
         where F: FnOnce() -> R
     {
@@ -1850,7 +1841,7 @@
         })
     }
 
-    /// Sets `context` as the new current ImplicitCtxt for the duration of the function `f`
+    /// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
     #[inline]
     pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R
     where
@@ -1861,19 +1852,19 @@
         })
     }
 
-    /// Enters GlobalCtxt by setting up libsyntax callbacks and
-    /// creating a initial TyCtxt and ImplicitCtxt.
-    /// This happens once per rustc session and TyCtxts only exists
+    /// Enters `GlobalCtxt` by setting up libsyntax callbacks and
+    /// creating a initial `TyCtxt` and `ImplicitCtxt`.
+    /// This happens once per rustc session and `TyCtxt`s only exists
     /// inside the `f` function.
     pub fn enter_global<'tcx, F, R>(gcx: &'tcx GlobalCtxt<'tcx>, f: F) -> R
     where
         F: FnOnce(TyCtxt<'tcx>) -> R,
     {
-        // Update GCX_PTR to indicate there's a GlobalCtxt available
+        // Update `GCX_PTR` to indicate there's a `GlobalCtxt` available.
         GCX_PTR.with(|lock| {
             *lock.lock() = gcx as *const _ as usize;
         });
-        // Set GCX_PTR back to 0 when we exit
+        // Set `GCX_PTR` back to 0 when we exit.
         let _on_drop = OnDrop(move || {
             GCX_PTR.with(|lock| *lock.lock() = 0);
         });
@@ -1894,12 +1885,12 @@
     }
 
     scoped_thread_local! {
-        /// Stores a pointer to the GlobalCtxt if one is available.
-        /// This is used to access the GlobalCtxt in the deadlock handler given to Rayon.
+        /// Stores a pointer to the `GlobalCtxt` if one is available.
+        /// This is used to access the `GlobalCtxt` in the deadlock handler given to Rayon.
         pub static GCX_PTR: Lock<usize>
     }
 
-    /// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local.
+    /// Creates a `TyCtxt` and `ImplicitCtxt` based on the `GCX_PTR` thread local.
     /// This is used in the deadlock handler.
     pub unsafe fn with_global<F, R>(f: F) -> R
     where
@@ -1921,7 +1912,7 @@
         enter_context(&icx, |_| f(tcx))
     }
 
-    /// Allows access to the current ImplicitCtxt in a closure if one is available
+    /// Allows access to the current `ImplicitCtxt` in a closure if one is available.
     #[inline]
     pub fn with_context_opt<F, R>(f: F) -> R
     where
@@ -1931,16 +1922,16 @@
         if context == 0 {
             f(None)
         } else {
-            // We could get a ImplicitCtxt pointer from another thread.
-            // Ensure that ImplicitCtxt is Sync
+            // We could get a `ImplicitCtxt` pointer from another thread.
+            // Ensure that `ImplicitCtxt` is `Sync`.
             sync::assert_sync::<ImplicitCtxt<'_, '_>>();
 
             unsafe { f(Some(&*(context as *const ImplicitCtxt<'_, '_>))) }
         }
     }
 
-    /// Allows access to the current ImplicitCtxt.
-    /// Panics if there is no ImplicitCtxt available
+    /// Allows access to the current `ImplicitCtxt`.
+    /// Panics if there is no `ImplicitCtxt` available.
     #[inline]
     pub fn with_context<F, R>(f: F) -> R
     where
@@ -1949,11 +1940,11 @@
         with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls")))
     }
 
-    /// Allows access to the current ImplicitCtxt whose tcx field has the same global
-    /// interner as the tcx argument passed in. This means the closure is given an ImplicitCtxt
-    /// with the same 'tcx lifetime as the TyCtxt passed in.
-    /// This will panic if you pass it a TyCtxt which has a different global interner from
-    /// the current ImplicitCtxt's tcx field.
+    /// Allows access to the current `ImplicitCtxt` whose tcx field has the same global
+    /// interner as the tcx argument passed in. This means the closure is given an `ImplicitCtxt`
+    /// with the same `'tcx` lifetime as the `TyCtxt` passed in.
+    /// This will panic if you pass it a `TyCtxt` which has a different global interner from
+    /// the current `ImplicitCtxt`'s `tcx` field.
     #[inline]
     pub fn with_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
     where
@@ -1968,8 +1959,8 @@
         })
     }
 
-    /// Allows access to the TyCtxt in the current ImplicitCtxt.
-    /// Panics if there is no ImplicitCtxt available
+    /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
+    /// Panics if there is no `ImplicitCtxt` available.
     #[inline]
     pub fn with<F, R>(f: F) -> R
     where
@@ -1978,8 +1969,8 @@
         with_context(|context| f(context.tcx))
     }
 
-    /// Allows access to the TyCtxt in the current ImplicitCtxt.
-    /// The closure is passed None if there is no ImplicitCtxt available
+    /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
+    /// The closure is passed None if there is no `ImplicitCtxt` available.
     #[inline]
     pub fn with_opt<F, R>(f: F) -> R
     where
@@ -1991,7 +1982,7 @@
 
 macro_rules! sty_debug_print {
     ($ctxt: expr, $($variant: ident),*) => {{
-        // curious inner module to allow variant names to be used as
+        // Curious inner module to allow variant names to be used as
         // variable names.
         #[allow(non_snake_case)]
         mod inner {
@@ -2265,9 +2256,9 @@
     projs: _intern_projs(ProjectionKind)
 );
 
-// This isn't a perfect fit: CanonicalVarInfo slices are always
+// This isn't a perfect fit: `CanonicalVarInfo` slices are always
 // allocated in the global arena, so this `intern_method!` macro is
-// overly general.  But we just return false for the code that checks
+// overly general. However, we just return `false` for the code that checks
 // whether they belong in the thread-local arena, so no harm done, and
 // seems better than open-coding the rest.
 intern_method! {
@@ -2366,7 +2357,7 @@
 
     #[inline]
     pub fn mk_adt(self, def: &'tcx AdtDef, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        // take a copy of substs so that we own the vectors inside
+        // Take a copy of substs so that we own the vectors inside.
         self.mk_ty(Adt(def, substs))
     }
 
@@ -2403,6 +2394,12 @@
     }
 
     #[inline]
+    pub fn mk_lang_item(self, ty: Ty<'tcx>, item: lang_items::LangItem)  -> Option<Ty<'tcx>> {
+        let def_id = self.lang_items().require(item).ok()?;
+        Some(self.mk_generic_adt(def_id, ty))
+    }
+
+    #[inline]
     pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem, None);
         self.mk_generic_adt(def_id, ty)
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index c70006b..62910ec 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -4,6 +4,7 @@
 use std::fmt;
 use rustc_target::spec::abi;
 use syntax::ast;
+use syntax::errors::pluralise;
 use errors::{Applicability, DiagnosticBuilder};
 use syntax_pos::Span;
 
@@ -46,6 +47,8 @@
     ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
 
     ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
+
+    IntrinsicCast,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
@@ -80,12 +83,6 @@
             }
         };
 
-        macro_rules! pluralise {
-            ($x:expr) => {
-                if $x != 1 { "s" } else { "" }
-            };
-        }
-
         match *self {
             CyclicTy(_) => write!(f, "cyclic type of infinite size"),
             Mismatch => write!(f, "types differ"),
@@ -179,6 +176,9 @@
             ConstMismatch(ref values) => {
                 write!(f, "expected `{}`, found `{}`", values.expected, values.found)
             }
+            IntrinsicCast => {
+                write!(f, "cannot coerce intrinsics to function pointers")
+            }
         }
     }
 }
@@ -195,7 +195,9 @@
             ty::Array(_, n) => {
                 let n = tcx.lift_to_global(&n).unwrap();
                 match n.try_eval_usize(tcx, ty::ParamEnv::empty()) {
-                    Some(n) => format!("array of {} elements", n).into(),
+                    Some(n) => {
+                        format!("array of {} element{}", n, if n != 1 { "s" } else { "" }).into()
+                    }
                     None => "array".into(),
                 }
             }
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 4b30412..1e08ae4 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -39,8 +39,8 @@
 use std::fmt;
 use crate::util::nodemap::FxHashSet;
 
-/// The TypeFoldable trait is implemented for every type that can be folded.
-/// Basically, every type that has a corresponding method in TypeFolder.
+/// This trait is implemented for every type that can be folded.
+/// Basically, every type that has a corresponding method in `TypeFolder`.
 ///
 /// To implement this conveniently, use the
 /// `BraceStructTypeFoldableImpl` etc macros found in `macros.rs`.
diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs
index 4453624..63cc60d 100644
--- a/src/librustc/ty/inhabitedness/def_id_forest.rs
+++ b/src/librustc/ty/inhabitedness/def_id_forest.rs
@@ -4,20 +4,20 @@
 use crate::ty::context::TyCtxt;
 use crate::ty::{DefId, DefIdTree};
 
-/// Represents a forest of DefIds closed under the ancestor relation. That is,
-/// if a DefId representing a module is contained in the forest then all
-/// DefIds defined in that module or submodules are also implicitly contained
+/// Represents a forest of `DefId`s closed under the ancestor relation. That is,
+/// if a `DefId` representing a module is contained in the forest then all
+/// `DefId`s defined in that module or submodules are also implicitly contained
 /// in the forest.
 ///
 /// This is used to represent a set of modules in which a type is visibly
 /// uninhabited.
 #[derive(Clone)]
 pub struct DefIdForest {
-    /// The minimal set of DefIds required to represent the whole set.
-    /// If A and B are DefIds in the DefIdForest, and A is a descendant
-    /// of B, then only B will be in root_ids.
-    /// We use a SmallVec here because (for its use for caching inhabitedness)
-    /// its rare that this will contain even two ids.
+    /// The minimal set of `DefId`s required to represent the whole set.
+    /// If A and B are DefIds in the `DefIdForest`, and A is a descendant
+    /// of B, then only B will be in `root_ids`.
+    /// We use a `SmallVec` here because (for its use for caching inhabitedness)
+    /// its rare that this will contain even two IDs.
     root_ids: SmallVec<[DefId; 1]>,
 }
 
@@ -37,7 +37,7 @@
         DefIdForest::from_id(crate_id)
     }
 
-    /// Creates a forest containing a DefId and all its descendants.
+    /// Creates a forest containing a `DefId` and all its descendants.
     pub fn from_id(id: DefId) -> DefIdForest {
         let mut root_ids = SmallVec::new();
         root_ids.push(id);
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 2b32916..1a0e351 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -1,3 +1,5 @@
+pub use self::def_id_forest::DefIdForest;
+
 use crate::ty::context::TyCtxt;
 use crate::ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
 use crate::ty::{DefId, SubstsRef};
@@ -5,12 +7,10 @@
 use crate::ty::TyKind::*;
 use crate::ty;
 
-pub use self::def_id_forest::DefIdForest;
-
 mod def_id_forest;
 
-// The methods in this module calculate DefIdForests of modules in which a
-// AdtDef/VariantDef/FieldDef is visibly uninhabited.
+// The methods in this module calculate `DefIdForest`s of modules in which a
+// `AdtDef`/`VariantDef`/`FieldDef` is visibly uninhabited.
 //
 // # Example
 // ```rust
@@ -36,24 +36,25 @@
 //     y: c::AlsoSecretlyUninhabited,
 // }
 // ```
-// In this code, the type Foo will only be visibly uninhabited inside the
-// modules b, c and d. Calling uninhabited_from on Foo or its AdtDef will
-// return the forest of modules {b, c->d} (represented in a DefIdForest by the
-// set {b, c})
+// In this code, the type `Foo` will only be visibly uninhabited inside the
+// modules `b`, `c` and `d`. Calling `uninhabited_from` on `Foo` or its `AdtDef` will
+// return the forest of modules {`b`, `c`->`d`} (represented in a `DefIdForest` by the
+// set {`b`, `c`}).
 //
-// We need this information for pattern-matching on Foo or types that contain
-// Foo.
+// We need this information for pattern-matching on `Foo` or types that contain
+// `Foo`.
 //
 // # Example
 // ```rust
 // let foo_result: Result<T, Foo> = ... ;
 // let Ok(t) = foo_result;
 // ```
-// This code should only compile in modules where the uninhabitedness of Foo is
+// This code should only compile in modules where the uninhabitedness of `Foo` is
 // visible.
 
 impl<'tcx> TyCtxt<'tcx> {
     /// Checks whether a type is visibly uninhabited from a particular module.
+    ///
     /// # Example
     /// ```rust
     /// enum Void {}
@@ -91,7 +92,7 @@
     /// visible.
     pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool {
         // To check whether this type is uninhabited at all (not just from the
-        // given node) you could check whether the forest is empty.
+        // given node), you could check whether the forest is empty.
         // ```
         // forest.is_empty()
         // ```
@@ -108,7 +109,7 @@
 }
 
 impl<'tcx> AdtDef {
-    /// Calculate the forest of DefIds from which this adt is visibly uninhabited.
+    /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
     fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest {
         // Non-exhaustive ADTs from other crates are always considered inhabited.
         if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
@@ -122,7 +123,7 @@
 }
 
 impl<'tcx> VariantDef {
-    /// Calculate the forest of DefIds from which this variant is visibly uninhabited.
+    /// Calculates the forest of `DefId`s from which this variant is visibly uninhabited.
     pub fn uninhabited_from(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -148,7 +149,7 @@
 }
 
 impl<'tcx> FieldDef {
-    /// Calculate the forest of DefIds from which this field is visibly uninhabited.
+    /// Calculates the forest of `DefId`s from which this field is visibly uninhabited.
     fn uninhabited_from(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -159,7 +160,7 @@
             self.ty(tcx, substs).uninhabited_from(tcx)
         };
         // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
-        // Visibility::Invisible so we need to override self.vis if we're
+        // `Visibility::Invisible` so we need to override `self.vis` if we're
         // dealing with an enum.
         if is_enum {
             data_uninhabitedness()
@@ -178,7 +179,7 @@
 }
 
 impl<'tcx> TyS<'tcx> {
-    /// Calculate the forest of DefIds from which this type is visibly uninhabited.
+    /// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
     fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest {
         match self.sty {
             Adt(def, substs) => def.uninhabited_from(tcx, substs),
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 56505c0..5ca819e 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -46,7 +46,7 @@
 use syntax::ast::{self, Name, Ident, NodeId};
 use syntax::attr;
 use syntax::ext::hygiene::ExpnId;
-use syntax::symbol::{kw, sym, Symbol, LocalInternedString, InternedString};
+use syntax::symbol::{kw, sym, Symbol, InternedString};
 use syntax_pos::Span;
 
 use smallvec;
@@ -590,7 +590,7 @@
 pub type CanonicalTy<'tcx> = Canonical<'tcx, Ty<'tcx>>;
 
 extern {
-    /// A dummy type used to force List to by unsized without requiring fat pointers
+    /// A dummy type used to force `List` to by unsized without requiring fat pointers.
     type OpaqueListContents;
 }
 
@@ -1938,9 +1938,15 @@
     pub vis: Visibility,
 }
 
-/// The definition of an abstract data type -- a struct or enum.
+/// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`.
 ///
 /// These are all interned (by `intern_adt_def`) into the `adt_defs` table.
+///
+/// The initialism *"Adt"* stands for an [*algebraic data type (ADT)*][adt].
+/// This is slightly wrong because `union`s are not ADTs.
+/// Moreover, Rust only allows recursive data types through indirection.
+///
+/// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type
 pub struct AdtDef {
     /// `DefId` of the struct, enum or union item.
     pub did: DefId,
@@ -2894,6 +2900,13 @@
     pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId)
                                         -> Option<ImplOverlapKind>
     {
+        // If either trait impl references an error, they're allowed to overlap,
+        // as one of them essentially doesn't exist.
+        if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error()) ||
+            self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error()) {
+            return Some(ImplOverlapKind::Permitted);
+        }
+
         let is_legit = if self.features().overlapping_marker_traits {
             let trait1_is_empty = self.impl_trait_ref(def_id1)
                 .map_or(false, |trait_ref| {
@@ -3386,10 +3399,6 @@
             name: InternedString::intern(name)
         }
     }
-
-    pub fn as_str(&self) -> LocalInternedString {
-        self.name.as_str()
-    }
 }
 
 impl fmt::Display for SymbolName {
diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs
index 092e7c6..50789bf 100644
--- a/src/librustc/ty/print/mod.rs
+++ b/src/librustc/ty/print/mod.rs
@@ -27,7 +27,8 @@
 /// which the associated types allow passing through the methods.
 ///
 /// For pretty-printing/formatting in particular, see `PrettyPrinter`.
-// FIXME(eddyb) find a better name, this is more general than "printing".
+//
+// FIXME(eddyb) find a better name; this is more general than "printing".
 pub trait Printer<'tcx>: Sized {
     type Error;
 
@@ -46,6 +47,7 @@
     ) -> Result<Self::Path, Self::Error> {
         self.default_print_def_path(def_id, substs)
     }
+
     fn print_impl_path(
         self,
         impl_def_id: DefId,
@@ -80,6 +82,7 @@
         self,
         cnum: CrateNum,
     ) -> Result<Self::Path, Self::Error>;
+
     fn path_qualified(
         self,
         self_ty: Ty<'tcx>,
@@ -93,11 +96,13 @@
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
     ) -> Result<Self::Path, Self::Error>;
+
     fn path_append(
         self,
         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
         disambiguated_data: &DisambiguatedDefPathData,
     ) -> Result<Self::Path, Self::Error>;
+
     fn path_generic_args(
         self,
         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index bf6741d..d995801 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -8,10 +8,11 @@
 use crate::ty::subst::{Kind, Subst, UnpackedKind};
 use crate::ty::layout::{Integer, IntegerExt, Size};
 use crate::mir::interpret::{ConstValue, sign_extend, Scalar, truncate};
-use syntax::ast;
+
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_target::spec::abi::Abi;
+use syntax::ast;
 use syntax::attr::{SignedInt, UnsignedInt};
 use syntax::symbol::{kw, InternedString};
 
@@ -194,7 +195,7 @@
         value.skip_binder().print(self)
     }
 
-    /// Print comma-separated elements.
+    /// Prints comma-separated elements.
     fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
     where
         T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
@@ -209,14 +210,14 @@
         Ok(self)
     }
 
-    /// Print `<...>` around what `f` prints.
+    /// Prints `<...>` around what `f` prints.
     fn generic_delimiters(
         self,
         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
     ) -> Result<Self, Self::Error>;
 
-    /// Return `true` if the region should be printed in
-    /// optional positions, e.g. `&'a T` or `dyn Tr + 'b`.
+    /// Returns `true` if the region should be printed in
+    /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
     /// This is typically the case for all non-`'_` regions.
     fn region_should_not_be_omitted(
         &self,
@@ -226,7 +227,7 @@
     // Defaults (should not be overriden):
 
     /// If possible, this returns a global path resolving to `def_id` that is visible
-    /// from at least one local module and returns true. If the crate defining `def_id` is
+    /// from at least one local module, and returns `true`. If the crate defining `def_id` is
     /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
     fn try_print_visible_def_path(
         self,
@@ -267,11 +268,11 @@
             // In local mode, when we encounter a crate other than
             // LOCAL_CRATE, execution proceeds in one of two ways:
             //
-            // 1. for a direct dependency, where user added an
+            // 1. For a direct dependency, where user added an
             //    `extern crate` manually, we put the `extern
             //    crate` as the parent. So you wind up with
             //    something relative to the current crate.
-            // 2. for an extern inferred from a path or an indirect crate,
+            // 2. For an extern inferred from a path or an indirect crate,
             //    where there is no explicit `extern crate`, we just prepend
             //    the crate name.
             match self.tcx().extern_crate(def_id) {
@@ -304,13 +305,13 @@
         let mut cur_def_key = self.tcx().def_key(def_id);
         debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
 
-        // For a constructor we want the name of its parent rather than <unnamed>.
+        // For a constructor, we want the name of its parent rather than <unnamed>.
         match cur_def_key.disambiguated_data.data {
             DefPathData::Ctor => {
                 let parent = DefId {
                     krate: def_id.krate,
                     index: cur_def_key.parent
-                        .expect("DefPathData::Ctor/VariantData missing a parent"),
+                        .expect("`DefPathData::Ctor` / `VariantData` missing a parent"),
                 };
 
                 cur_def_key = self.tcx().def_key(parent);
@@ -630,7 +631,7 @@
                         sep = ", ";
                     }
                 } else {
-                    // cross-crate closure types should only be
+                    // Cross-crate closure types should only be
                     // visible in codegen bug reports, I imagine.
                     p!(write("@{:?}", did));
                     let mut sep = " ";
@@ -673,7 +674,7 @@
                         sep = ", ";
                     }
                 } else {
-                    // cross-crate closure types should only be
+                    // Cross-crate closure types should only be
                     // visible in codegen bug reports, I imagine.
                     p!(write("@{:?}", did));
                     let mut sep = " ";
@@ -944,10 +945,16 @@
                         .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
                 },
                 (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
-                    Some(&data.bytes[start..end])
+                    // The `inspect` here is okay since we checked the bounds, and there are no
+                    // relocations (we have an active slice reference here). We don't use this
+                    // result to affect interpreter execution.
+                    Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
                 },
                 (ConstValue::Slice { data, start, end }, ty::Str) => {
-                    let slice = &data.bytes[start..end];
+                    // The `inspect` here is okay since we checked the bounds, and there are no
+                    // relocations (we have an active `str` reference here). We don't use this
+                    // result to affect interpreter execution.
+                    let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
                     let s = ::std::str::from_utf8(slice)
                         .expect("non utf8 str from miri");
                     p!(write("{:?}", s));
@@ -1167,6 +1174,7 @@
         }
         Ok(self)
     }
+
     fn path_qualified(
         mut self,
         self_ty: Ty<'tcx>,
@@ -1195,6 +1203,7 @@
         self.empty_path = false;
         Ok(self)
     }
+
     fn path_append(
         mut self,
         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
@@ -1232,6 +1241,7 @@
 
         Ok(self)
     }
+
     fn path_generic_args(
         mut self,
         print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 674f894..4cef6a0 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -5,9 +5,6 @@
 use crate::ich::{CachingSourceMapView, Fingerprint};
 use crate::mir::{self, interpret};
 use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
-                      SpecializedDecoder, SpecializedEncoder,
-                      UseSpecializedDecodable, UseSpecializedEncodable};
 use crate::session::{CrateDisambiguator, Session};
 use crate::ty::{self, Ty};
 use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
@@ -19,6 +16,10 @@
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_serialize::{
+    Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder,
+    UseSpecializedDecodable, UseSpecializedEncodable, opaque,
+};
 use std::mem;
 use syntax::ast::{Ident, NodeId};
 use syntax::source_map::{SourceMap, StableSourceFileId};
@@ -37,17 +38,16 @@
 const TAG_VALID_SPAN: u8 = 0;
 const TAG_INVALID_SPAN: u8 = 1;
 
-/// `OnDiskCache` provides an interface to incr. comp. data cached from the
+/// Provides an interface to incremental compilation data cached from the
 /// previous compilation session. This data will eventually include the results
 /// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
 /// any diagnostics that have been emitted during a query.
 pub struct OnDiskCache<'sess> {
-
     // The complete cache data in serialized form.
     serialized_data: Vec<u8>,
 
-    // This field collects all Diagnostics emitted during the current
-    // compilation session.
+    // Collects all `Diagnostic`s emitted during the current compilation
+    // session.
     current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
 
     prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
@@ -56,7 +56,7 @@
     source_map: &'sess SourceMap,
     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
 
-    // These two fields caches that are populated lazily during decoding.
+    // Caches that are populated lazily during decoding.
     file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
     synthetic_syntax_contexts: Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
 
@@ -78,7 +78,7 @@
     prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
     query_result_index: EncodedQueryResultIndex,
     diagnostics_index: EncodedQueryResultIndex,
-    // the location of all allocations
+    // The location of all allocations.
     interpret_alloc_index: Vec<u32>,
 }
 
@@ -104,28 +104,28 @@
 }
 
 impl<'sess> OnDiskCache<'sess> {
-    /// Creates a new OnDiskCache instance from the serialized data in `data`.
-    pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> OnDiskCache<'sess> {
+    /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
+    pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
         debug_assert!(sess.opts.incremental.is_some());
 
-        // Wrapping in a scope so we can borrow `data`
+        // Wrap in a scope so we can borrow `data`.
         let footer: Footer = {
             let mut decoder = opaque::Decoder::new(&data[..], start_pos);
 
-            // Decode the *position* of the footer which can be found in the
+            // Decode the *position* of the footer, which can be found in the
             // last 8 bytes of the file.
             decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE);
-            let query_result_index_pos = IntEncodedWithFixedSize::decode(&mut decoder)
-                .expect("Error while trying to decode query result index position.")
+            let footer_pos = IntEncodedWithFixedSize::decode(&mut decoder)
+                .expect("error while trying to decode footer position")
                 .0 as usize;
 
-            // Decoder the file footer which contains all the lookup tables, etc.
-            decoder.set_position(query_result_index_pos);
+            // Decode the file footer, which contains all the lookup tables, etc.
+            decoder.set_position(footer_pos);
             decode_tagged(&mut decoder, TAG_FILE_FOOTER)
-                .expect("Error while trying to decode query result index position.")
+                .expect("error while trying to decode footer position")
         };
 
-        OnDiskCache {
+        Self {
             serialized_data: data,
             file_index_to_stable_id: footer.file_index_to_stable_id,
             file_index_to_file: Default::default(),
@@ -140,8 +140,8 @@
         }
     }
 
-    pub fn new_empty(source_map: &'sess SourceMap) -> OnDiskCache<'sess> {
-        OnDiskCache {
+    pub fn new_empty(source_map: &'sess SourceMap) -> Self {
+        Self {
             serialized_data: Vec::new(),
             file_index_to_stable_id: Default::default(),
             file_index_to_file: Default::default(),
@@ -158,11 +158,11 @@
 
     pub fn serialize<'tcx, E>(&self, tcx: TyCtxt<'tcx>, encoder: &mut E) -> Result<(), E::Error>
     where
-        E: ty_codec::TyEncoder,
+        E: TyEncoder,
     {
-        // Serializing the DepGraph should not modify it:
+        // Serializing the `DepGraph` should not modify it.
         tcx.dep_graph.with_ignore(|| {
-            // Allocate SourceFileIndices
+            // Allocate `SourceFileIndex`es.
             let (file_to_file_index, file_index_to_stable_id) = {
                 let files = tcx.sess.source_map().files();
                 let mut file_to_file_index = FxHashMap::with_capacity_and_hasher(
@@ -197,7 +197,7 @@
             // be in memory, so this should be a cheap operation.
             tcx.dep_graph.exec_cache_promotions(tcx);
 
-            // Encode query results
+            // Encode query results.
             let mut query_result_index = EncodedQueryResultIndex::new();
 
             time(tcx.sess, "encode query results", || {
@@ -221,29 +221,28 @@
                 Ok(())
             })?;
 
-            // Encode diagnostics
+            // Encode diagnostics.
             let diagnostics_index: EncodedDiagnosticsIndex = self.current_diagnostics.borrow()
                 .iter()
-                .map(|(dep_node_index, diagnostics)|
-            {
-                let pos = AbsoluteBytePos::new(encoder.position());
-                // Let's make sure we get the expected type here:
-                let diagnostics: &EncodedDiagnostics = diagnostics;
-                let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
-                encoder.encode_tagged(dep_node_index, diagnostics)?;
+                .map(|(dep_node_index, diagnostics)| {
+                    let pos = AbsoluteBytePos::new(encoder.position());
+                    // Let's make sure we get the expected type here.
+                    let diagnostics: &EncodedDiagnostics = diagnostics;
+                    let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
+                    encoder.encode_tagged(dep_node_index, diagnostics)?;
 
-                Ok((dep_node_index, pos))
-            })
-            .collect::<Result<_, _>>()?;
+                    Ok((dep_node_index, pos))
+                })
+                .collect::<Result<_, _>>()?;
 
             let interpret_alloc_index = {
                 let mut interpret_alloc_index = Vec::new();
                 let mut n = 0;
                 loop {
                     let new_n = encoder.interpret_allocs_inverse.len();
-                    // if we have found new ids, serialize those, too
+                    // If we have found new IDs, serialize those too.
                     if n == new_n {
-                        // otherwise, abort
+                        // Otherwise, abort.
                         break;
                     }
                     interpret_alloc_index.reserve(new_n - n);
@@ -263,13 +262,15 @@
             };
 
             let sorted_cnums = sorted_cnums_including_local_crate(tcx);
-            let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
-                let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
-                let crate_disambiguator = tcx.crate_disambiguator(cnum);
-                (cnum.as_u32(), crate_name, crate_disambiguator)
-            }).collect();
+            let prev_cnums: Vec<_> = sorted_cnums.iter()
+                .map(|&cnum| {
+                    let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
+                    let crate_disambiguator = tcx.crate_disambiguator(cnum);
+                    (cnum.as_u32(), crate_name, crate_disambiguator)
+                })
+                .collect();
 
-            // Encode the file footer
+            // Encode the file footer.
             let footer_pos = encoder.position() as u64;
             encoder.encode_tagged(TAG_FILE_FOOTER, &Footer {
                 file_index_to_stable_id,
@@ -371,7 +372,7 @@
     {
         let pos = index.get(&dep_node_index).cloned()?;
 
-        // Initialize the cnum_map using the value from the thread which finishes the closure first
+        // Initialize `cnum_map` using the value from the thread that finishes the closure first.
         self.cnum_map.init_nonlocking_same(|| {
             Self::compute_cnum_map(tcx, &self.prev_cnums[..])
         });
@@ -381,25 +382,21 @@
             opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
             source_map: self.source_map,
             cnum_map: self.cnum_map.get(),
+            synthetic_syntax_contexts: &self.synthetic_syntax_contexts,
             file_index_to_file: &self.file_index_to_file,
             file_index_to_stable_id: &self.file_index_to_stable_id,
-            synthetic_syntax_contexts: &self.synthetic_syntax_contexts,
             alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
         };
 
         match decode_tagged(&mut decoder, dep_node_index) {
-            Ok(value) => {
-                Some(value)
-            }
-            Err(e) => {
-                bug!("Could not decode cached {}: {}", debug_tag, e)
-            }
+            Ok(v) => Some(v),
+            Err(e) => bug!("could not decode cached {}: {}", debug_tag, e),
         }
     }
 
-    // This function builds mapping from previous-session-CrateNum to
-    // current-session-CrateNum. There might be CrateNums from the previous
-    // Session that don't occur in the current one. For these, the mapping
+    // This function builds mapping from previous-session-`CrateNum` to
+    // current-session-`CrateNum`. There might be `CrateNum`s from the previous
+    // `Session` that don't occur in the current one. For these, the mapping
     // maps to None.
     fn compute_cnum_map(
         tcx: TyCtxt<'_>,
@@ -432,9 +429,9 @@
 
 //- DECODING -------------------------------------------------------------------
 
-/// A decoder that can read the incr. comp. cache. It is similar to the one
-/// we use for crate metadata decoding in that it can rebase spans and
-/// eventually will also handle things that contain `Ty` instances.
+/// A decoder that can read fro the incr. comp. cache. It is similar to the one
+/// we use for crate metadata decoding in that it can rebase spans and eventually
+/// will also handle things that contain `Ty` instances.
 struct CacheDecoder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     opaque: opaque::Decoder<'a>,
@@ -458,7 +455,7 @@
         file_index_to_file.borrow_mut().entry(index).or_insert_with(|| {
             let stable_id = file_index_to_stable_id[&index];
             source_map.source_file_by_stable_id(stable_id)
-                .expect("Failed to lookup SourceFile in new context.")
+                .expect("failed to lookup `SourceFile` in new context")
         }).clone()
     }
 }
@@ -479,7 +476,7 @@
     }
 }
 
-// Decode something that was encoded with encode_tagged() and verify that the
+// Decodes something that was encoded with `encode_tagged()` and verify that the
 // tag matches and the correct amount of bytes was read.
 fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> Result<V, D::Error>
 where
@@ -500,7 +497,7 @@
     Ok(value)
 }
 
-impl<'a, 'tcx> ty_codec::TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
+impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
@@ -534,7 +531,7 @@
         }
 
         let ty = or_insert_with(self)?;
-        // This may overwrite the entry, but it should overwrite with the same value
+        // This may overwrite the entry, but it should overwrite with the same value.
         tcx.rcache.borrow_mut().insert_same(cache_key, ty);
         Ok(ty)
     }
@@ -553,7 +550,7 @@
 
     fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
         self.cnum_map[cnum].unwrap_or_else(|| {
-            bug!("Could not find new CrateNum for {:?}", cnum)
+            bug!("could not find new `CrateNum` for {:?}", cnum)
         })
     }
 }
@@ -635,25 +632,25 @@
 }
 
 // This impl makes sure that we get a runtime error when we try decode a
-// DefIndex that is not contained in a DefId. Such a case would be problematic
-// because we would not know how to transform the DefIndex to the current
+// `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
+// because we would not know how to transform the `DefIndex` to the current
 // context.
 impl<'a, 'tcx> SpecializedDecoder<DefIndex> for CacheDecoder<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
-        bug!("Trying to decode DefIndex outside the context of a DefId")
+        bug!("trying to decode `DefIndex` outside the context of a `DefId`")
     }
 }
 
-// Both the CrateNum and the DefIndex of a DefId can change in between two
-// compilation sessions. We use the DefPathHash, which is stable across
-// sessions, to map the old DefId to the new one.
+// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
+// compilation sessions. We use the `DefPathHash`, which is stable across
+// sessions, to map the old DefId`` to the new one.
 impl<'a, 'tcx> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx> {
     #[inline]
     fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
-        // Load the DefPathHash which is was we encoded the DefId as.
+        // Load the `DefPathHash` which is was we encoded the `DefId` as.
         let def_path_hash = DefPathHash::decode(self)?;
 
-        // Using the DefPathHash, we can lookup the new DefId
+        // Using the `DefPathHash`, we can lookup the new `DefId`.
         Ok(self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash])
     }
 }
@@ -667,10 +664,10 @@
 
 impl<'a, 'tcx> SpecializedDecoder<hir::HirId> for CacheDecoder<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<hir::HirId, Self::Error> {
-        // Load the DefPathHash which is was we encoded the DefIndex as.
+        // Load the `DefPathHash` which is what we encoded the `DefIndex` as.
         let def_path_hash = DefPathHash::decode(self)?;
 
-        // Use the DefPathHash to map to the current DefId.
+        // Use the `DefPathHash` to map to the current `DefId`.
         let def_id = self.tcx()
                          .def_path_hash_to_def_id
                          .as_ref()
@@ -678,10 +675,10 @@
 
         debug_assert!(def_id.is_local());
 
-        // The ItemLocalId needs no remapping.
+        // The `ItemLocalId` needs no remapping.
         let local_id = hir::ItemLocalId::decode(self)?;
 
-        // Reconstruct the HirId and look up the corresponding NodeId in the
+        // Reconstruct the `HirId` and look up the corresponding `NodeId` in the
         // context of the current session.
         Ok(hir::HirId {
             owner: def_id.index,
@@ -690,8 +687,8 @@
     }
 }
 
-// NodeIds are not stable across compilation sessions, so we store them in their
-// HirId representation. This allows use to map them to the current NodeId.
+// `NodeId`s are not stable across compilation sessions, so we store them in their
+// `HirId` representation. This allows use to map them to the current `NodeId`.
 impl<'a, 'tcx> SpecializedDecoder<NodeId> for CacheDecoder<'a, 'tcx> {
     #[inline]
     fn specialized_decode(&mut self) -> Result<NodeId, Self::Error> {
@@ -728,6 +725,7 @@
 
 //- ENCODING -------------------------------------------------------------------
 
+/// An encoder that can write the incr. comp. cache.
 struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> {
     tcx: TyCtxt<'tcx>,
     encoder: &'a mut E,
@@ -742,7 +740,7 @@
 
 impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
         self.file_to_file_index[&(&*source_file as *const SourceFile)]
@@ -753,11 +751,11 @@
     /// encode the specified tag, then the given value, then the number of
     /// bytes taken up by tag and value. On decoding, we can then verify that
     /// we get the expected tag and read the expected number of bytes.
-    fn encode_tagged<T: Encodable, V: Encodable>(&mut self,
-                                                 tag: T,
-                                                 value: &V)
-                                                 -> Result<(), E::Error>
-    {
+    fn encode_tagged<T: Encodable, V: Encodable>(
+        &mut self,
+        tag: T,
+        value: &V
+    ) -> Result<(), E::Error> {
         let start_pos = self.position();
 
         tag.encode(self)?;
@@ -770,7 +768,7 @@
 
 impl<'a, 'tcx, E> SpecializedEncoder<interpret::AllocId> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
         use std::collections::hash_map::Entry;
@@ -790,10 +788,9 @@
 
 impl<'a, 'tcx, E> SpecializedEncoder<Span> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
-
         if *span == DUMMY_SP {
             return TAG_INVALID_SPAN.encode(self);
         }
@@ -849,14 +846,14 @@
         // We don't currently encode enough information to ensure hygiene works
         // with incremental, so panic rather than risk incremental bugs.
 
-        // FIXME: Handle hygiene in incremental
-        bug!("Trying to encode Ident for incremental")
+        // FIXME: handle hygiene in incremental.
+        bug!("trying to encode `Ident` for incremental");
     }
 }
 
 impl<'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     #[inline]
     fn position(&self) -> usize {
@@ -866,7 +863,7 @@
 
 impl<'a, 'tcx, E> SpecializedEncoder<CrateNum> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     #[inline]
     fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
@@ -876,7 +873,7 @@
 
 impl<'a, 'tcx, E> SpecializedEncoder<Ty<'tcx>> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     #[inline]
     fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
@@ -887,7 +884,7 @@
 
 impl<'a, 'tcx, E> SpecializedEncoder<ty::GenericPredicates<'tcx>> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     #[inline]
     fn specialized_encode(&mut self,
@@ -900,7 +897,7 @@
 
 impl<'a, 'tcx, E> SpecializedEncoder<hir::HirId> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     #[inline]
     fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> {
@@ -918,7 +915,7 @@
 
 impl<'a, 'tcx, E> SpecializedEncoder<DefId> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     #[inline]
     fn specialized_encode(&mut self, id: &DefId) -> Result<(), Self::Error> {
@@ -929,7 +926,7 @@
 
 impl<'a, 'tcx, E> SpecializedEncoder<LocalDefId> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     #[inline]
     fn specialized_encode(&mut self, id: &LocalDefId) -> Result<(), Self::Error> {
@@ -939,18 +936,18 @@
 
 impl<'a, 'tcx, E> SpecializedEncoder<DefIndex> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     fn specialized_encode(&mut self, _: &DefIndex) -> Result<(), Self::Error> {
-        bug!("Encoding DefIndex without context.")
+        bug!("encoding `DefIndex` without context");
     }
 }
 
-// NodeIds are not stable across compilation sessions, so we store them in their
-// HirId representation. This allows use to map them to the current NodeId.
+// `NodeId`s are not stable across compilation sessions, so we store them in their
+// `HirId` representation. This allows use to map them to the current `NodeId`.
 impl<'a, 'tcx, E> SpecializedEncoder<NodeId> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     #[inline]
     fn specialized_encode(&mut self, node_id: &NodeId) -> Result<(), Self::Error> {
@@ -967,7 +964,7 @@
 
 impl<'a, 'tcx, E, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
     T: Encodable,
 {
     #[inline]
@@ -996,7 +993,7 @@
 
 impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + TyEncoder,
 {
     type Error = E::Error;
 
@@ -1040,7 +1037,7 @@
 impl SpecializedEncoder<IntEncodedWithFixedSize> for opaque::Encoder {
     fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> {
         let start_pos = self.position();
-        for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE {
+        for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE {
             ((x.0 >> i * 8) as u8).encode(self)?;
         }
         let end_pos = self.position();
@@ -1085,10 +1082,10 @@
             if Q::cache_on_disk(tcx, key.clone(), Some(&entry.value)) {
                 let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
-                // Record position of the cache entry
+                // Record position of the cache entry.
                 query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
 
-                // Encode the type check tables with the SerializedDepNodeIndex
+                // Encode the type check tables with the `SerializedDepNodeIndex`
                 // as tag.
                 encoder.encode_tagged(dep_node, &entry.value)?;
             }
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 4dce55f..d199a26 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -61,7 +61,7 @@
     }
 }
 
-// If enabled, send a message to the profile-queries thread
+// If enabled, sends a message to the profile-queries thread.
 macro_rules! profq_msg {
     ($tcx:expr, $msg:expr) => {
         if cfg!(debug_assertions) {
@@ -72,7 +72,7 @@
     }
 }
 
-// If enabled, format a key using its debug string, which can be
+// If enabled, formats a key using its debug string, which can be
 // expensive to compute (in terms of time).
 macro_rules! profq_query_msg {
     ($query:expr, $tcx:expr, $key:expr) => {{
@@ -98,7 +98,7 @@
 
 impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
     /// Either gets a `JobOwner` corresponding the query, allowing us to
-    /// start executing the query, or it returns with the result of the query.
+    /// start executing the query, or returns with the result of the query.
     /// If the query is executing elsewhere, this will wait for it.
     /// If the query panicked, this will silently panic.
     ///
@@ -215,30 +215,30 @@
     #[inline(never)]
     #[cold]
     fn drop(&mut self) {
-        // Poison the query so jobs waiting on it panic
+        // Poison the query so jobs waiting on it panic.
         let shard = self.cache.get_shard_by_value(&self.key);
         shard.lock().active.insert(self.key.clone(), QueryResult::Poisoned);
         // Also signal the completion of the job, so waiters
-        // will continue execution
+        // will continue execution.
         self.job.signal_complete();
     }
 }
 
 #[derive(Clone)]
 pub struct CycleError<'tcx> {
-    /// The query and related span which uses the cycle
+    /// The query and related span that uses the cycle.
     pub(super) usage: Option<(Span, Query<'tcx>)>,
     pub(super) cycle: Vec<QueryInfo<'tcx>>,
 }
 
-/// The result of `try_get_lock`
+/// The result of `try_get_lock`.
 pub(super) enum TryGetJob<'a, 'tcx, D: QueryDescription<'tcx>> {
     /// The query is not yet started. Contains a guard to the cache eventually used to start it.
     NotYetStarted(JobOwner<'a, 'tcx, D>),
 
     /// The query was already completed.
-    /// Returns the result of the query and its dep node index
-    /// if it succeeded or a cycle error if it failed
+    /// Returns the result of the query and its dep-node index
+    /// if it succeeded or a cycle error if it failed.
     JobCompleted((D::Value, DepNodeIndex)),
 
     /// Trying to execute the query resulted in a cycle.
@@ -246,7 +246,7 @@
 }
 
 impl<'tcx> TyCtxt<'tcx> {
-    /// Executes a job by changing the ImplicitCtxt to point to the
+    /// Executes a job by changing the `ImplicitCtxt` to point to the
     /// new query job while it executes. It returns the diagnostics
     /// captured during execution and the actual result.
     #[inline(always)]
@@ -259,11 +259,11 @@
     where
         F: FnOnce(TyCtxt<'tcx>) -> R,
     {
-        // The TyCtxt stored in TLS has the same global interner lifetime
+        // The `TyCtxt` stored in TLS has the same global interner lifetime
         // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
-        // when accessing the ImplicitCtxt
+        // when accessing the `ImplicitCtxt`.
         tls::with_related_context(self, move |current_icx| {
-            // Update the ImplicitCtxt to point to our new query job
+            // Update the `ImplicitCtxt` to point to our new query job.
             let new_icx = tls::ImplicitCtxt {
                 tcx: self.global_tcx(),
                 query: Some(job),
@@ -272,7 +272,7 @@
                 task_deps: current_icx.task_deps,
             };
 
-            // Use the ImplicitCtxt while we execute the query
+            // Use the `ImplicitCtxt` while we execute the query.
             tls::enter_context(&new_icx, |_| {
                 compute(self.global_tcx())
             })
@@ -372,7 +372,7 @@
         };
 
         // Fast path for when incr. comp. is off. `to_dep_node` is
-        // expensive for some DepKinds.
+        // expensive for some `DepKind`s.
         if !self.dep_graph.is_fully_enabled() {
             let null_dep_node = DepNode::new_no_params(crate::dep_graph::DepKind::Null);
             return self.force_query_with_job::<Q>(key, job, null_dep_node).0;
@@ -410,7 +410,7 @@
         if !Q::EVAL_ALWAYS {
             // The diagnostics for this query will be
             // promoted to the current session during
-            // try_mark_green(), so we can ignore them here.
+            // `try_mark_green()`, so we can ignore them here.
             let loaded = self.start_query(job.job.clone(), None, |tcx| {
                 let marked = tcx.dep_graph.try_mark_green_and_read(tcx, &dep_node);
                 marked.map(|(prev_dep_node_index, dep_node_index)| {
@@ -441,11 +441,11 @@
         dep_node: &DepNode,
     ) -> Q::Value {
         // Note this function can be called concurrently from the same query
-        // We must ensure that this is handled correctly
+        // We must ensure that this is handled correctly.
 
         debug_assert!(self.dep_graph.is_green(dep_node));
 
-        // First we try to load the result from the on-disk cache
+        // First we try to load the result from the on-disk cache.
         let result = if Q::cache_on_disk(self.global_tcx(), key.clone(), None) &&
                         self.sess.opts.debugging_opts.incremental_queries {
             self.sess.profiler(|p| p.incremental_load_result_start(Q::NAME));
@@ -453,10 +453,10 @@
             self.sess.profiler(|p| p.incremental_load_result_end(Q::NAME));
 
             // We always expect to find a cached result for things that
-            // can be forced from DepNode.
+            // can be forced from `DepNode`.
             debug_assert!(!dep_node.kind.can_reconstruct_query_key() ||
                           result.is_some(),
-                          "Missing on-disk cache entry for {:?}",
+                          "missing on-disk cache entry for {:?}",
                           dep_node);
             result
         } else {
@@ -475,8 +475,7 @@
 
             self.sess.profiler(|p| p.start_query(Q::NAME));
 
-            // The dep-graph for this computation is already in
-            // place
+            // The dep-graph for this computation is already in-place.
             let result = self.dep_graph.with_ignore(|| {
                 Q::compute(self, key)
             });
@@ -485,7 +484,7 @@
             result
         };
 
-        // If -Zincremental-verify-ich is specified, re-hash results from
+        // If `-Zincremental-verify-ich` is specified, re-hash results from
         // the cache and make sure that they have the expected fingerprint.
         if unlikely!(self.sess.opts.debugging_opts.incremental_verify_ich) {
             self.incremental_verify_ich::<Q>(&result, dep_node, dep_node_index);
@@ -508,10 +507,12 @@
     ) {
         use crate::ich::Fingerprint;
 
-        assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) ==
+        assert!(
+            Some(self.dep_graph.fingerprint_of(dep_node_index)) ==
                 self.dep_graph.prev_fingerprint_of(dep_node),
-                "Fingerprint for green query instance not loaded \
-                    from cache: {:?}", dep_node);
+            "fingerprint for green query instance not loaded from cache: {:?}",
+            dep_node,
+        );
 
         debug!("BEGIN verify_ich({:?})", dep_node);
         let mut hcx = self.create_stable_hashing_context();
@@ -521,8 +522,11 @@
 
         let old_hash = self.dep_graph.fingerprint_of(dep_node_index);
 
-        assert!(new_hash == old_hash, "Found unstable fingerprints \
-            for {:?}", dep_node);
+        assert!(
+            new_hash == old_hash,
+            "found unstable fingerprints for {:?}",
+            dep_node,
+        );
     }
 
     #[inline(always)]
@@ -534,11 +538,11 @@
     ) -> (Q::Value, DepNodeIndex) {
         // If the following assertion triggers, it can have two reasons:
         // 1. Something is wrong with DepNode creation, either here or
-        //    in DepGraph::try_mark_green()
-        // 2. Two distinct query keys get mapped to the same DepNode
-        //    (see for example #48923)
+        //    in `DepGraph::try_mark_green()`.
+        // 2. Two distinct query keys get mapped to the same `DepNode`
+        //    (see for example #48923).
         assert!(!self.dep_graph.dep_node_exists(&dep_node),
-                "Forcing query with already existing DepNode.\n\
+                "forcing query with already existing `DepNode`\n\
                  - query-key: {:?}\n\
                  - dep-node: {:?}",
                 key, dep_node);
@@ -584,7 +588,7 @@
     }
 
     /// Ensure that either this query has all green inputs or been executed.
-    /// Executing query::ensure(D) is considered a read of the dep-node D.
+    /// Executing `query::ensure(D)` is considered a read of the dep-node `D`.
     ///
     /// This function is particularly useful when executing passes for their
     /// side-effects -- e.g., in order to report errors for erroneous programs.
@@ -899,13 +903,13 @@
                 }
             }
 
-            // FIXME(eddyb) Get more valid Span's on queries.
+            // FIXME(eddyb) Get more valid `Span`s on queries.
             pub fn default_span(&self, tcx: TyCtxt<$tcx>, span: Span) -> Span {
                 if !span.is_dummy() {
                     return span;
                 }
-                // The def_span query is used to calculate default_span,
-                // so exit to avoid infinite recursion
+                // The `def_span` query is used to calculate `default_span`,
+                // so exit to avoid infinite recursion.
                 if let Query::def_span(..) = *self {
                     return span
                 }
@@ -1116,7 +1120,7 @@
         impl<$tcx> Default for Providers<$tcx> {
             fn default() -> Self {
                 $(fn $name<$tcx>(_: TyCtxt<$tcx>, key: $K) -> $R {
-                    bug!("tcx.{}({:?}) unsupported by its crate",
+                    bug!("`tcx.{}({:?})` unsupported by its crate",
                          stringify!($name), key);
                 })*
                 Providers { $($name),* }
@@ -1128,26 +1132,26 @@
 
 /// The red/green evaluation system will try to mark a specific DepNode in the
 /// dependency graph as green by recursively trying to mark the dependencies of
-/// that DepNode as green. While doing so, it will sometimes encounter a DepNode
+/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
 /// where we don't know if it is red or green and we therefore actually have
 /// to recompute its value in order to find out. Since the only piece of
-/// information that we have at that point is the DepNode we are trying to
+/// information that we have at that point is the `DepNode` we are trying to
 /// re-evaluate, we need some way to re-run a query from just that. This is what
 /// `force_from_dep_node()` implements.
 ///
-/// In the general case, a DepNode consists of a DepKind and an opaque
+/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
 /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
 /// is usually constructed by computing a stable hash of the query-key that the
-/// DepNode corresponds to. Consequently, it is not in general possible to go
+/// `DepNode` corresponds to. Consequently, it is not in general possible to go
 /// back from hash to query-key (since hash functions are not reversible). For
 /// this reason `force_from_dep_node()` is expected to fail from time to time
-/// because we just cannot find out, from the DepNode alone, what the
+/// because we just cannot find out, from the `DepNode` alone, what the
 /// corresponding query-key is and therefore cannot re-run the query.
 ///
 /// The system deals with this case letting `try_mark_green` fail which forces
 /// the root query to be re-evaluated.
 ///
-/// Now, if force_from_dep_node() would always fail, it would be pretty useless.
+/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
 /// Fortunately, we can use some contextual information that will allow us to
 /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
 /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
@@ -1171,9 +1175,9 @@
 pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
     use crate::dep_graph::RecoverKey;
 
-    // We must avoid ever having to call force_from_dep_node() for a
-    // DepNode::codegen_unit:
-    // Since we cannot reconstruct the query key of a DepNode::codegen_unit, we
+    // We must avoid ever having to call `force_from_dep_node()` for a
+    // `DepNode::codegen_unit`:
+    // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
     // would always end up having to evaluate the first caller of the
     // `codegen_unit` query that *is* reconstructible. This might very well be
     // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
@@ -1196,7 +1200,7 @@
             if let Some(def_id) = dep_node.extract_def_id(tcx) {
                 def_id
             } else {
-                // return from the whole function
+                // Return from the whole function.
                 return false
             }
         }
@@ -1224,20 +1228,20 @@
 
     rustc_dep_node_force!([dep_node, tcx]
         // These are inputs that are expected to be pre-allocated and that
-        // should therefore always be red or green already
+        // should therefore always be red or green already.
         DepKind::AllLocalTraitImpls |
         DepKind::Krate |
         DepKind::CrateMetadata |
         DepKind::HirBody |
         DepKind::Hir |
 
-        // This are anonymous nodes
+        // These are anonymous nodes.
         DepKind::TraitSelect |
 
         // We don't have enough information to reconstruct the query key of
-        // these
+        // these.
         DepKind::CompileCodegenUnit => {
-            bug!("force_from_dep_node() - Encountered {:?}", dep_node)
+            bug!("force_from_dep_node: encountered {:?}", dep_node)
         }
 
         DepKind::Analysis => { force!(analysis, krate!()); }
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 649a5244..ec7cf1a 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -748,6 +748,7 @@
             Sorts(ref x) => return tcx.lift(x).map(Sorts),
             ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
             ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
+            IntrinsicCast => IntrinsicCast,
         })
     }
 }
@@ -1338,6 +1339,7 @@
         (ty::error::TypeError::Sorts)(x),
         (ty::error::TypeError::ExistentialMismatch)(x),
         (ty::error::TypeError::ConstMismatch)(x),
+        (ty::error::TypeError::IntrinsicCast),
     }
 }
 
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index d2edf6f..e73a51e 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -644,7 +644,7 @@
 impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List<ExistentialPredicate<'tcx>> {}
 
 impl<'tcx> List<ExistentialPredicate<'tcx>> {
-    /// Returns the "principal def id" of this set of existential predicates.
+    /// Returns the "principal `DefId`" of this set of existential predicates.
     ///
     /// A Rust trait object type consists (in addition to a lifetime bound)
     /// of a set of trait bounds, which are separated into any number
@@ -1052,7 +1052,7 @@
     }
 }
 
-/// Signature of a function type, which I have arbitrarily
+/// Signature of a function type, which we have arbitrarily
 /// decided to use to refer to the input/output types.
 ///
 /// - `inputs`: is the list of arguments and their modes.
@@ -1076,7 +1076,8 @@
         self.inputs_and_output[self.inputs_and_output.len() - 1]
     }
 
-    // Create a minimal `FnSig` to be used when encountering a `TyKind::Error` in a fallible method
+    // Creates a minimal `FnSig` to be used when encountering a `TyKind::Error` in a fallible
+    // method.
     fn fake() -> FnSig<'tcx> {
         FnSig {
             inputs_and_output: List::empty(),
@@ -1118,7 +1119,6 @@
 
 pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<FnSig<'tcx>>>;
 
-
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord,
          Hash, RustcEncodable, RustcDecodable, HashStable)]
 pub struct ParamTy {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 7a77418..78d94df 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -709,8 +709,10 @@
                 substs: SubstsRef<'tcx>,
             ) -> Option<Ty<'tcx>> {
                 if self.found_recursion {
-                    None
-                } else if self.seen_opaque_tys.insert(def_id) {
+                    return None;
+                }
+                let substs = substs.fold_with(self);
+                if self.seen_opaque_tys.insert(def_id) {
                     let generic_ty = self.tcx.type_of(def_id);
                     let concrete_ty = generic_ty.subst(self.tcx, substs);
                     let expanded_ty = self.fold_ty(concrete_ty);
@@ -994,6 +996,24 @@
         debug!("is_type_representable: {:?} is {:?}", self, r);
         r
     }
+
+    /// Peel off all reference types in this type until there are none left.
+    ///
+    /// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`.
+    ///
+    /// # Examples
+    ///
+    /// - `u8` -> `u8`
+    /// - `&'a mut u8` -> `u8`
+    /// - `&'a &'b u8` -> `u8`
+    /// - `&'a *const &'b u8 -> *const &'b u8`
+    pub fn peel_refs(&'tcx self) -> Ty<'tcx> {
+        let mut ty = self;
+        while let Ref(_, inner_ty, _) = ty.sty {
+            ty = inner_ty;
+        }
+        ty
+    }
 }
 
 fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 7118d05..2475b93 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -5,17 +5,13 @@
 use std::cell::{RefCell, Cell};
 use std::fmt::Debug;
 use std::hash::Hash;
-use std::panic;
-use std::env;
 use std::time::{Duration, Instant};
 
 use std::sync::mpsc::{Sender};
 use syntax_pos::{SpanData};
 use syntax::symbol::{Symbol, sym};
 use rustc_macros::HashStable;
-use crate::ty::TyCtxt;
 use crate::dep_graph::{DepNode};
-use lazy_static;
 use crate::session::Session;
 
 #[cfg(test)]
@@ -31,39 +27,6 @@
 
 thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
 
-lazy_static! {
-    static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static> = {
-        let hook = panic::take_hook();
-        panic::set_hook(Box::new(panic_hook));
-        hook
-    };
-}
-
-fn panic_hook(info: &panic::PanicInfo<'_>) {
-    (*DEFAULT_HOOK)(info);
-
-    let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
-
-    if backtrace {
-        TyCtxt::try_print_query_stack();
-    }
-
-    #[cfg(windows)]
-    unsafe {
-        if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
-            extern "system" {
-                fn DebugBreak();
-            }
-            // Trigger a debugger if we crashed during bootstrap.
-            DebugBreak();
-        }
-    }
-}
-
-pub fn install_panic_hook() {
-    lazy_static::initialize(&DEFAULT_HOOK);
-}
-
 /// Parameters to the `Dump` variant of type `ProfileQueriesMsg`.
 #[derive(Clone,Debug)]
 pub struct ProfQDumpParams {
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
index a2b4b09..645707c 100644
--- a/src/librustc_asan/build.rs
+++ b/src/librustc_asan/build.rs
@@ -4,6 +4,10 @@
 use cmake::Config;
 
 fn main() {
+    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
+    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
+        return;
+    }
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
         build_helper::restore_library_path();
 
diff --git a/src/librustc_ast_borrowck/borrowck/mod.rs b/src/librustc_ast_borrowck/borrowck/mod.rs
index 3bbd7ae..23d5480 100644
--- a/src/librustc_ast_borrowck/borrowck/mod.rs
+++ b/src/librustc_ast_borrowck/borrowck/mod.rs
@@ -9,7 +9,6 @@
 
 use rustc::hir::HirId;
 use rustc::hir::Node;
-use rustc::cfg;
 use rustc::middle::borrowck::{BorrowCheckResult, SignalledError};
 use rustc::hir::def_id::{DefId, LocalDefId};
 use rustc::middle::mem_categorization as mc;
@@ -28,6 +27,7 @@
 
 use rustc::hir;
 
+use crate::cfg;
 use crate::dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom};
 
 pub mod check_loans;
diff --git a/src/librustc_ast_borrowck/borrowck/move_data.rs b/src/librustc_ast_borrowck/borrowck/move_data.rs
index 887a0e2..67d8181 100644
--- a/src/librustc_ast_borrowck/borrowck/move_data.rs
+++ b/src/librustc_ast_borrowck/borrowck/move_data.rs
@@ -4,7 +4,7 @@
 use crate::dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom};
 
 use crate::borrowck::*;
-use rustc::cfg;
+use crate::cfg;
 use rustc::ty::{self, TyCtxt};
 use rustc::util::nodemap::FxHashMap;
 
diff --git a/src/librustc/cfg/construct.rs b/src/librustc_ast_borrowck/cfg/construct.rs
similarity index 84%
rename from src/librustc/cfg/construct.rs
rename to src/librustc_ast_borrowck/cfg/construct.rs
index 0dad2dd..0dc9990 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc_ast_borrowck/cfg/construct.rs
@@ -1,11 +1,12 @@
 use crate::cfg::*;
-use crate::middle::region;
-use rustc_data_structures::graph::implementation as graph;
-use crate::ty::{self, TyCtxt};
 
-use crate::hir::{self, PatKind};
-use crate::hir::def_id::DefId;
-use crate::hir::ptr::P;
+use rustc::hir::{self, PatKind};
+use rustc::hir::def_id::DefId;
+use rustc::hir::ptr::P;
+use rustc::middle::region;
+use rustc::ty::{self, TyCtxt};
+
+use rustc_data_structures::graph::implementation as graph;
 
 struct CFGBuilder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -19,18 +20,18 @@
 
 #[derive(Copy, Clone)]
 struct BlockScope {
-    block_expr_id: hir::ItemLocalId, // id of breakable block expr node
+    block_expr_id: hir::ItemLocalId, // ID of breakable block expr node
     break_index: CFGIndex, // where to go on `break`
 }
 
 #[derive(Copy, Clone)]
 struct LoopScope {
-    loop_id: hir::ItemLocalId,     // id of loop/while node
+    loop_id: hir::ItemLocalId, // ID of `loop`/`while` node
     continue_index: CFGIndex, // where to go on a `loop`
-    break_index: CFGIndex,    // where to go on a `break`
+    break_index: CFGIndex, // where to go on a `break`
 }
 
-pub fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG {
+pub(super) fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG {
     let mut graph = graph::Graph::new();
     let entry = graph.add_node(CFGNodeData::Entry);
 
@@ -103,9 +104,7 @@
                 let init_exit = self.opt_expr(&local.init, pred);
                 self.pat(&local.pat, init_exit)
             }
-            hir::StmtKind::Item(_) => {
-                pred
-            }
+            hir::StmtKind::Item(_) => pred,
             hir::StmtKind::Expr(ref expr) |
             hir::StmtKind::Semi(ref expr) => {
                 self.expr(&expr, pred)
@@ -154,12 +153,12 @@
         }
     }
 
-    fn pats_all<'b, I: Iterator<Item=&'b P<hir::Pat>>>(
+    /// Handles case where all of the patterns must match.
+    fn pats_all<'b, I: Iterator<Item = &'b P<hir::Pat>>>(
         &mut self,
         pats: I,
-        pred: CFGIndex
+        pred: CFGIndex,
     ) -> CFGIndex {
-        //! Handles case where all of the patterns must match.
         pats.fold(pred, |pred, pat| self.pat(&pat, pred))
     }
 
@@ -185,15 +184,15 @@
                 // Note that `break` and `loop` statements
                 // may cause additional edges.
 
-                let loopback = self.add_dummy_node(&[pred]);              // 1
-                let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]);          // 2
+                let loopback = self.add_dummy_node(&[pred]); // 1
+                let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 2
                 self.loop_scopes.push(LoopScope {
                     loop_id: expr.hir_id.local_id,
                     continue_index: loopback,
                     break_index: expr_exit,
                 });
-                let body_exit = self.block(&body, loopback);           // 3
-                self.add_contained_edge(body_exit, loopback);            // 4
+                let body_exit = self.block(&body, loopback); // 3
+                self.add_contained_edge(body_exit, loopback); // 4
                 self.loop_scopes.pop();
                 expr_exit
             }
@@ -217,9 +216,9 @@
                 //    v 3  v 4
                 //   [..exit..]
                 //
-                let l_exit = self.expr(&l, pred);                      // 1
-                let r_exit = self.expr(&r, l_exit);                    // 2
-                self.add_ast_node(expr.hir_id.local_id, &[l_exit, r_exit])            // 3,4
+                let l_exit = self.expr(&l, pred); // 1
+                let r_exit = self.expr(&r, l_exit); // 2
+                self.add_ast_node(expr.hir_id.local_id, &[l_exit, r_exit]) // 3,4
             }
 
             hir::ExprKind::Ret(ref v) => {
@@ -313,11 +312,13 @@
         }
     }
 
-    fn call<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
-            call_expr: &hir::Expr,
-            pred: CFGIndex,
-            func_or_rcvr: &hir::Expr,
-            args: I) -> CFGIndex {
+    fn call<'b, I: Iterator<Item = &'b hir::Expr>>(
+        &mut self,
+        call_expr: &hir::Expr,
+        pred: CFGIndex,
+        func_or_rcvr: &hir::Expr,
+        args: I,
+    ) -> CFGIndex {
         let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
         let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
         let m = self.tcx.hir().get_module_parent(call_expr.hir_id);
@@ -328,33 +329,38 @@
         }
     }
 
-    fn exprs<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
-                                             exprs: I,
-                                             pred: CFGIndex) -> CFGIndex {
-        //! Constructs graph for `exprs` evaluated in order
+    /// Constructs graph for `exprs` evaluated in order.
+    fn exprs<'b, I: Iterator<Item = &'b hir::Expr>>(
+        &mut self,
+        exprs: I,
+        pred: CFGIndex,
+    ) -> CFGIndex {
         exprs.fold(pred, |p, e| self.expr(e, p))
     }
 
-    fn opt_expr(&mut self,
-                opt_expr: &Option<P<hir::Expr>>,
-                pred: CFGIndex) -> CFGIndex {
-        //! Constructs graph for `opt_expr` evaluated, if Some
+    /// Constructs graph for `opt_expr` evaluated, if `Some`.
+    fn opt_expr(
+        &mut self,
+        opt_expr: &Option<P<hir::Expr>>,
+        pred: CFGIndex,
+    ) -> CFGIndex {
         opt_expr.iter().fold(pred, |p, e| self.expr(&e, p))
     }
 
-    fn straightline<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
-                    expr: &hir::Expr,
-                    pred: CFGIndex,
-                    subexprs: I) -> CFGIndex {
-        //! Handles case of an expression that evaluates `subexprs` in order
-
+    /// Handles case of an expression that evaluates `subexprs` in order.
+    fn straightline<'b, I: Iterator<Item = &'b hir::Expr>>(
+        &mut self,
+        expr: &hir::Expr,
+        pred: CFGIndex,
+        subexprs: I,
+    ) -> CFGIndex {
         let subexprs_exit = self.exprs(subexprs, pred);
         self.add_ast_node(expr.hir_id.local_id, &[subexprs_exit])
     }
 
     fn match_(&mut self, id: hir::ItemLocalId, discr: &hir::Expr,
               arms: &[hir::Arm], pred: CFGIndex) -> CFGIndex {
-        // The CFG for match expression is quite complex, so no ASCII
+        // The CFG for match expressions is quite complex, so no ASCII
         // art for it (yet).
         //
         // The CFG generated below matches roughly what MIR contains.
@@ -369,13 +375,13 @@
         //
         // What is going on is explained in further comments.
 
-        // Visit the discriminant expression
+        // Visit the discriminant expression.
         let discr_exit = self.expr(discr, pred);
 
         // Add a node for the exit of the match expression as a whole.
         let expr_exit = self.add_ast_node(id, &[]);
 
-        // Keep track of the previous guard expressions
+        // Keep track of the previous guard expressions.
         let mut prev_guard = None;
         let match_scope = region::Scope { id, data: region::ScopeData::Node };
 
@@ -388,12 +394,12 @@
                 // Visit the pattern, coming from the discriminant exit
                 let mut pat_exit = self.pat(&pat, discr_exit);
 
-                // If there is a guard expression, handle it here
+                // If there is a guard expression, handle it here.
                 if let Some(ref guard) = arm.guard {
                     // Add a dummy node for the previous guard
-                    // expression to target
+                    // expression to target.
                     let guard_start = self.add_dummy_node(&[pat_exit]);
-                    // Visit the guard expression
+                    // Visit the guard expression.
                     let guard_exit = match guard {
                         hir::Guard::If(ref e) => (&**e, self.expr(e, guard_start)),
                     };
@@ -407,24 +413,23 @@
                         self.add_exiting_edge(prev_guard, prev_index, match_scope, guard_start);
                     }
 
-                    // Push the guard onto the list of previous guards
+                    // Push the guard onto the list of previous guards.
                     prev_guard = Some(guard_exit);
 
-                    // Update the exit node for the pattern
+                    // Update the exit node for the pattern.
                     pat_exit = guard_exit.1;
                 }
 
-                // Add an edge from the exit of this pattern to the
-                // exit of the arm
+                // Add an edge from the exit of this pattern to the exit of the arm.
                 self.add_contained_edge(pat_exit, bindings_exit);
             }
 
-            // Visit the body of this arm
+            // Visit the body of this arm.
             let body_exit = self.expr(&arm.body, bindings_exit);
 
             let arm_exit = self.add_ast_node(arm.hir_id.local_id, &[body_exit]);
 
-            // Link the body to the exit of the expression
+            // Link the body to the exit of the expression.
             self.add_contained_edge(arm_exit, expr_exit);
         }
 
@@ -451,18 +456,22 @@
         node
     }
 
-    fn add_contained_edge(&mut self,
-                          source: CFGIndex,
-                          target: CFGIndex) {
+    fn add_contained_edge(
+        &mut self,
+        source: CFGIndex,
+        target: CFGIndex,
+    ) {
         let data = CFGEdgeData {exiting_scopes: vec![] };
         self.graph.add_edge(source, target, data);
     }
 
-    fn add_exiting_edge(&mut self,
-                        from_expr: &hir::Expr,
-                        from_index: CFGIndex,
-                        target_scope: region::Scope,
-                        to_index: CFGIndex) {
+    fn add_exiting_edge(
+        &mut self,
+        from_expr: &hir::Expr,
+        from_index: CFGIndex,
+        target_scope: region::Scope,
+        to_index: CFGIndex,
+    ) {
         let mut data = CFGEdgeData { exiting_scopes: vec![] };
         let mut scope = region::Scope {
             id: from_expr.hir_id.local_id,
@@ -476,9 +485,11 @@
         self.graph.add_edge(from_index, to_index, data);
     }
 
-    fn add_returning_edge(&mut self,
-                          _from_expr: &hir::Expr,
-                          from_index: CFGIndex) {
+    fn add_returning_edge(
+        &mut self,
+        _from_expr: &hir::Expr,
+        from_index: CFGIndex,
+    ) {
         let data = CFGEdgeData {
             exiting_scopes: self.loop_scopes.iter()
                                             .rev()
@@ -488,11 +499,12 @@
         self.graph.add_edge(from_index, self.fn_exit, data);
     }
 
-    fn find_scope_edge(&self,
-                  expr: &hir::Expr,
-                  destination: hir::Destination,
-                  scope_cf_kind: ScopeCfKind) -> (region::Scope, CFGIndex) {
-
+    fn find_scope_edge(
+        &self,
+        expr: &hir::Expr,
+        destination: hir::Destination,
+        scope_cf_kind: ScopeCfKind,
+    ) -> (region::Scope, CFGIndex) {
         match destination.target_id {
             Ok(loop_id) => {
                 for b in &self.breakable_block_scopes {
@@ -519,7 +531,7 @@
                         });
                     }
                 }
-                span_bug!(expr.span, "no scope for id {}", loop_id);
+                span_bug!(expr.span, "no scope for ID {}", loop_id);
             }
             Err(err) => span_bug!(expr.span, "scope error: {}",  err),
         }
diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc_ast_borrowck/cfg/graphviz.rs
similarity index 87%
rename from src/librustc/cfg/graphviz.rs
rename to src/librustc_ast_borrowck/cfg/graphviz.rs
index 9181200..99c6b49 100644
--- a/src/librustc/cfg/graphviz.rs
+++ b/src/librustc_ast_borrowck/cfg/graphviz.rs
@@ -1,21 +1,18 @@
-/// This module provides linkage between rustc::middle::graph and
+/// This module provides linkage between `rustc::middle::graph` and
 /// libgraphviz traits.
 
-// For clarity, rename the graphviz crate locally to dot.
-use graphviz as dot;
-
 use crate::cfg;
-use crate::hir;
-use crate::ty::TyCtxt;
+use rustc::hir;
+use rustc::ty::TyCtxt;
 
-pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode);
-pub type Edge<'a> = &'a cfg::CFGEdge;
+pub(crate) type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode);
+pub(crate) type Edge<'a> = &'a cfg::CFGEdge;
 
 pub struct LabelledCFG<'a, 'tcx> {
     pub tcx: TyCtxt<'tcx>,
     pub cfg: &'a cfg::CFG,
     pub name: String,
-    /// `labelled_edges` controls whether we emit labels on the edges
+    /// `labelled_edges` controls whether we emit labels on the edges.
     pub labelled_edges: bool,
 }
 
@@ -28,12 +25,12 @@
         };
         let s = self.tcx.hir().node_to_string(hir_id);
 
-        // Replacing newlines with \\l causes each line to be left-aligned,
+        // Replacing newlines with `\\l` causes each line to be left-aligned,
         // improving presentation of (long) pretty-printed expressions.
         if s.contains("\n") {
             let mut s = s.replace("\n", "\\l");
             // Apparently left-alignment applies to the line that precedes
-            // \l, not the line that follows; so, add \l at end of string
+            // `\l`, not the line that follows; so, add `\l` at end of string
             // if not already present, ensuring last line gets left-aligned
             // as well.
             let mut last_two: Vec<_> =
@@ -112,8 +109,7 @@
     }
 }
 
-impl<'a, 'hir> dot::GraphWalk<'a> for LabelledCFG<'a, 'hir>
-{
+impl<'a, 'hir> dot::GraphWalk<'a> for LabelledCFG<'a, 'hir> {
     type Node = Node<'a>;
     type Edge = Edge<'a>;
     fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() }
diff --git a/src/librustc_ast_borrowck/cfg/mod.rs b/src/librustc_ast_borrowck/cfg/mod.rs
new file mode 100644
index 0000000..981199c
--- /dev/null
+++ b/src/librustc_ast_borrowck/cfg/mod.rs
@@ -0,0 +1,55 @@
+//! Module that constructs a control-flow graph representing an item.
+//! Uses `Graph` as the underlying representation.
+
+use rustc_data_structures::graph::implementation as graph;
+use rustc::ty::TyCtxt;
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+
+mod construct;
+pub mod graphviz;
+
+pub struct CFG {
+    owner_def_id: DefId,
+    pub(crate) graph: CFGGraph,
+    pub(crate) entry: CFGIndex,
+    exit: CFGIndex,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum CFGNodeData {
+    AST(hir::ItemLocalId),
+    Entry,
+    Exit,
+    Dummy,
+    Unreachable,
+}
+
+impl CFGNodeData {
+    pub(crate) fn id(&self) -> hir::ItemLocalId {
+        if let CFGNodeData::AST(id) = *self {
+            id
+        } else {
+            hir::DUMMY_ITEM_LOCAL_ID
+        }
+    }
+}
+
+#[derive(Debug)]
+pub struct CFGEdgeData {
+    pub(crate) exiting_scopes: Vec<hir::ItemLocalId>
+}
+
+pub(crate) type CFGIndex = graph::NodeIndex;
+
+pub(crate) type CFGGraph = graph::Graph<CFGNodeData, CFGEdgeData>;
+
+pub(crate) type CFGNode = graph::Node<CFGNodeData>;
+
+pub(crate) type CFGEdge = graph::Edge<CFGEdgeData>;
+
+impl CFG {
+    pub fn new(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG {
+        construct::construct(tcx, body)
+    }
+}
diff --git a/src/librustc_ast_borrowck/dataflow.rs b/src/librustc_ast_borrowck/dataflow.rs
index 3a4c8c9..a856290 100644
--- a/src/librustc_ast_borrowck/dataflow.rs
+++ b/src/librustc_ast_borrowck/dataflow.rs
@@ -3,9 +3,7 @@
 //! and thus uses bitvectors. Your job is simply to specify the so-called
 //! GEN and KILL bits for each expression.
 
-use rustc::cfg;
-use rustc::cfg::CFGIndex;
-use rustc::ty::TyCtxt;
+use crate::cfg::{self, CFGIndex};
 use std::mem;
 use std::usize;
 use log::debug;
@@ -16,6 +14,7 @@
 use rustc::hir;
 use rustc::hir::intravisit;
 use rustc::hir::print as pprust;
+use rustc::ty::TyCtxt;
 
 #[derive(Copy, Clone, Debug)]
 pub enum EntryOrExit {
diff --git a/src/librustc_ast_borrowck/graphviz.rs b/src/librustc_ast_borrowck/graphviz.rs
index 7a8a23c..c077dc8 100644
--- a/src/librustc_ast_borrowck/graphviz.rs
+++ b/src/librustc_ast_borrowck/graphviz.rs
@@ -4,13 +4,12 @@
 
 pub use Variant::*;
 
-pub use rustc::cfg::graphviz::{Node, Edge};
-use rustc::cfg::graphviz as cfg_dot;
-
+pub(crate) use crate::cfg::graphviz::{Node, Edge};
+use crate::cfg::graphviz as cfg_dot;
+use crate::cfg::CFGIndex;
 use crate::borrowck::{self, BorrowckCtxt, LoanPath};
 use crate::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit};
 use log::debug;
-use rustc::cfg::CFGIndex;
 use std::rc::Rc;
 
 #[derive(Debug, Copy, Clone)]
diff --git a/src/librustc_ast_borrowck/lib.rs b/src/librustc_ast_borrowck/lib.rs
index dc81827..aea97fe 100644
--- a/src/librustc_ast_borrowck/lib.rs
+++ b/src/librustc_ast_borrowck/lib.rs
@@ -18,5 +18,6 @@
 pub mod graphviz;
 
 mod dataflow;
+pub mod cfg;
 
 pub use borrowck::provide;
diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml
index 5e1b0ea..98efa6a 100644
--- a/src/librustc_codegen_llvm/Cargo.toml
+++ b/src/librustc_codegen_llvm/Cargo.toml
@@ -11,11 +11,7 @@
 test = false
 
 [dependencies]
-cc = "1.0.1" # Used to locate MSVC
-num_cpus = "1.0"
-tempfile = "3.0"
 rustc_llvm = { path = "../librustc_llvm" }
-memmap = "0.6"
 
 [features]
 # This is used to convince Cargo to separately cache builds of `rustc_codegen_llvm`
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index ff87afe..2ca517d 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -229,7 +229,7 @@
                 // We instead thus allocate some scratch space...
                 let scratch_size = cast.size(bx);
                 let scratch_align = cast.align(bx);
-                let llscratch = bx.alloca(cast.llvm_type(bx), "abi_cast", scratch_align);
+                let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align);
                 bx.lifetime_start(llscratch, scratch_size);
 
                 // ...where we first store the value...
diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs
index e3b7cb2..68d3f90 100644
--- a/src/librustc_codegen_llvm/back/archive.rs
+++ b/src/librustc_codegen_llvm/back/archive.rs
@@ -12,6 +12,7 @@
 use rustc_codegen_ssa::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION};
 use rustc_codegen_ssa::back::archive::{ArchiveBuilder, find_library};
 use rustc::session::Session;
+use syntax::symbol::Symbol;
 
 struct ArchiveConfig<'a> {
     pub sess: &'a Session,
@@ -109,7 +110,7 @@
 
     /// Adds all of the contents of a native library to this archive. This will
     /// search in the relevant locations for a library named `name`.
-    fn add_native_library(&mut self, name: &str) {
+    fn add_native_library(&mut self, name: Symbol) {
         let location = find_library(name, &self.config.lib_search_paths,
                                     self.config.sess);
         self.add_archive(&location, |_| false).unwrap_or_else(|e| {
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 894e5c2..423a01a 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -5,7 +5,6 @@
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
-use syntax::symbol::LocalInternedString;
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind, RealPredicate};
 use rustc_codegen_ssa::MemFlags;
 use libc::{c_uint, c_char};
@@ -24,6 +23,7 @@
 use std::ops::{Deref, Range};
 use std::ptr;
 use std::iter::TrustedLen;
+use syntax::symbol::Symbol;
 
 // All Builders must have an llfn associated with them
 #[must_use]
@@ -387,23 +387,17 @@
         )
     }
 
-    fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
+    fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
         let mut bx = Builder::with_cx(self.cx);
         bx.position_at_start(unsafe {
             llvm::LLVMGetFirstBasicBlock(self.llfn())
         });
-        bx.dynamic_alloca(ty, name, align)
+        bx.dynamic_alloca(ty, align)
     }
 
-    fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
+    fn dynamic_alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
         unsafe {
-            let alloca = if name.is_empty() {
-                llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED)
-            } else {
-                let name = SmallCStr::new(name);
-                llvm::LLVMBuildAlloca(self.llbuilder, ty,
-                                      name.as_ptr())
-            };
+            let alloca = llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED);
             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
             alloca
         }
@@ -412,16 +406,9 @@
     fn array_alloca(&mut self,
                         ty: &'ll Type,
                         len: &'ll Value,
-                        name: &str,
                         align: Align) -> &'ll Value {
         unsafe {
-            let alloca = if name.is_empty() {
-                llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED)
-            } else {
-                let name = SmallCStr::new(name);
-                llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len,
-                                           name.as_ptr())
-            };
+            let alloca = llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED);
             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
             alloca
         }
@@ -561,7 +548,7 @@
 
         let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
         cg_elem.val.store(&mut body_bx,
-            PlaceRef::new_sized(current, cg_elem.layout, align));
+            PlaceRef::new_sized_aligned(current, cg_elem.layout, align));
 
         let next = body_bx.inbounds_gep(current, &[self.const_usize(1)]);
         body_bx.br(header_bx.llbb());
@@ -1082,8 +1069,8 @@
 
     fn static_panic_msg(
         &mut self,
-        msg: Option<LocalInternedString>,
-        filename: LocalInternedString,
+        msg: Option<Symbol>,
+        filename: Symbol,
         line: Self::Value,
         col: Self::Value,
         kind: &str,
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index 2c0a6f6..35d5107 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -37,7 +37,7 @@
         return llfn;
     }
 
-    let sym = tcx.symbol_name(instance).as_str();
+    let sym = tcx.symbol_name(instance).name.as_str();
     debug!("get_fn({:?}: {:?}) => {}", instance, sig, sym);
 
     // Create a fn pointer with the substituted signature.
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index 19f1808..6fbea96 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -17,7 +17,7 @@
 
 use libc::{c_uint, c_char};
 
-use syntax::symbol::LocalInternedString;
+use syntax::symbol::Symbol;
 use syntax::ast::Mutability;
 
 pub use crate::context::CodegenCx;
@@ -122,7 +122,7 @@
 
     fn const_cstr(
         &self,
-        s: LocalInternedString,
+        s: Symbol,
         null_terminated: bool,
     ) -> &'ll Value {
         unsafe {
@@ -130,9 +130,10 @@
                 return llval;
             }
 
+            let s_str = s.as_str();
             let sc = llvm::LLVMConstStringInContext(self.llcx,
-                                                    s.as_ptr() as *const c_char,
-                                                    s.len() as c_uint,
+                                                    s_str.as_ptr() as *const c_char,
+                                                    s_str.len() as c_uint,
                                                     !null_terminated as Bool);
             let sym = self.generate_local_symbol_name("str");
             let g = self.define_global(&sym[..], self.val_ty(sc)).unwrap_or_else(||{
@@ -147,8 +148,8 @@
         }
     }
 
-    pub fn const_str_slice(&self, s: LocalInternedString) -> &'ll Value {
-        let len = s.len();
+    pub fn const_str_slice(&self, s: Symbol) -> &'ll Value {
+        let len = s.as_str().len();
         let cs = consts::ptrcast(self.const_cstr(s, false),
             self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self)));
         self.const_fat_ptr(cs, self.const_usize(len as u64))
@@ -348,7 +349,7 @@
             )};
             self.const_bitcast(llval, llty)
         };
-        PlaceRef::new_sized(llval, layout, alloc.align)
+        PlaceRef::new_sized(llval, layout)
     }
 
     fn const_ptrcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 0077df3..e71d1fc 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -11,12 +11,11 @@
     Pointer, ErrorHandled, GlobalId};
 use rustc::mir::mono::MonoItem;
 use rustc::hir::Node;
-use syntax_pos::Span;
 use rustc_target::abi::HasDataLayout;
-use syntax::symbol::sym;
-use syntax_pos::symbol::LocalInternedString;
 use rustc::ty::{self, Ty, Instance};
 use rustc_codegen_ssa::traits::*;
+use syntax::symbol::{Symbol, sym};
+use syntax_pos::Span;
 
 use rustc::ty::layout::{self, Size, Align, LayoutOf};
 
@@ -25,21 +24,31 @@
 use std::ffi::{CStr, CString};
 
 pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
-    let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
+    let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1);
     let dl = cx.data_layout();
     let pointer_size = dl.pointer_size.bytes() as usize;
 
     let mut next_offset = 0;
-    for &(offset, ((), alloc_id)) in alloc.relocations.iter() {
+    for &(offset, ((), alloc_id)) in alloc.relocations().iter() {
         let offset = offset.bytes();
         assert_eq!(offset as usize as u64, offset);
         let offset = offset as usize;
         if offset > next_offset {
-            llvals.push(cx.const_bytes(&alloc.bytes[next_offset..offset]));
+            // This `inspect` is okay since we have checked that it is not within a relocation, it
+            // is within the bounds of the allocation, and it doesn't affect interpreter execution
+            // (we inspect the result after interpreter execution). Any undef byte is replaced with
+            // some arbitrary byte value.
+            //
+            // FIXME: relay undef bytes to codegen as undef const bytes
+            let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset);
+            llvals.push(cx.const_bytes(bytes));
         }
         let ptr_offset = read_target_uint(
             dl.endian,
-            &alloc.bytes[offset..(offset + pointer_size)],
+            // This `inspect` is okay since it is within the bounds of the allocation, it doesn't
+            // affect interpreter execution (we inspect the result after interpreter execution),
+            // and we properly interpret the relocation as a relocation pointer offset.
+            alloc.inspect_with_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
         ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
         llvals.push(cx.scalar_to_backend(
             Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
@@ -51,8 +60,16 @@
         ));
         next_offset = offset + pointer_size;
     }
-    if alloc.bytes.len() >= next_offset {
-        llvals.push(cx.const_bytes(&alloc.bytes[next_offset ..]));
+    if alloc.len() >= next_offset {
+        let range = next_offset..alloc.len();
+        // This `inspect` is okay since we have check that it is after all relocations, it is
+        // within the bounds of the allocation, and it doesn't affect interpreter execution (we
+        // inspect the result after interpreter execution). Any undef byte is replaced with some
+        // arbitrary byte value.
+        //
+        // FIXME: relay undef bytes to codegen as undef const bytes
+        let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range);
+        llvals.push(cx.const_bytes(bytes));
     }
 
     cx.const_struct(&llvals, true)
@@ -104,10 +121,11 @@
     cx: &CodegenCx<'ll, 'tcx>,
     attrs: &CodegenFnAttrs,
     ty: Ty<'tcx>,
-    sym: LocalInternedString,
+    sym: Symbol,
     span: Span
 ) -> &'ll Value {
     let llty = cx.layout_of(ty).llvm_type(cx);
+    let sym = sym.as_str();
     if let Some(linkage) = attrs.linkage {
         debug!("get_static: sym={} linkage={:?}", sym, linkage);
 
@@ -203,7 +221,7 @@
                  def_id);
 
         let ty = instance.ty(self.tcx);
-        let sym = self.tcx.symbol_name(instance).as_str();
+        let sym = self.tcx.symbol_name(instance).name.as_symbol();
 
         debug!("get_static: sym={} instance={:?}", sym, instance);
 
@@ -214,11 +232,12 @@
                 Node::Item(&hir::Item {
                     ref attrs, span, node: hir::ItemKind::Static(..), ..
                 }) => {
-                    if self.get_declared_value(&sym[..]).is_some() {
+                    let sym_str = sym.as_str();
+                    if self.get_declared_value(&sym_str).is_some() {
                         span_bug!(span, "Conflicting symbol names for static?");
                     }
 
-                    let g = self.define_global(&sym[..], llty).unwrap();
+                    let g = self.define_global(&sym_str, llty).unwrap();
 
                     if !self.tcx.is_reachable_non_generic(def_id) {
                         unsafe {
@@ -437,7 +456,23 @@
                 //
                 // We could remove this hack whenever we decide to drop macOS 10.10 support.
                 if self.tcx.sess.target.target.options.is_like_osx {
-                    let sect_name = if alloc.bytes.iter().all(|b| *b == 0) {
+                    assert_eq!(alloc.relocations().len(), 0);
+
+                    let is_zeroed = {
+                        // Treats undefined bytes as if they were defined with the byte value that
+                        // happens to be currently assigned in mir. This is valid since reading
+                        // undef bytes may yield arbitrary values.
+                        //
+                        // FIXME: ignore undef bytes even with representation `!= 0`.
+                        //
+                        // The `inspect` method is okay here because we checked relocations, and
+                        // because we are doing this access to inspect the final interpreter state
+                        // (not as part of the interpreter execution).
+                        alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len())
+                            .iter()
+                            .all(|b| *b == 0)
+                    };
+                    let sect_name = if is_zeroed {
                         CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
                     } else {
                         CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
@@ -456,10 +491,17 @@
                         section.as_str().as_ptr() as *const _,
                         section.as_str().len() as c_uint,
                     );
+                    assert!(alloc.relocations().is_empty());
+
+                    // The `inspect` method is okay here because we checked relocations, and
+                    // because we are doing this access to inspect the final interpreter state (not
+                    // as part of the interpreter execution).
+                    let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(
+                        0..alloc.len());
                     let alloc = llvm::LLVMMDStringInContext(
                         self.llcx,
-                        alloc.bytes.as_ptr() as *const _,
-                        alloc.bytes.len() as c_uint,
+                        bytes.as_ptr() as *const _,
+                        bytes.len() as c_uint,
                     );
                     let data = [section, alloc];
                     let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2);
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index a2aaadd..58ce970 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -29,7 +29,7 @@
 use std::iter;
 use std::str;
 use std::sync::Arc;
-use syntax::symbol::LocalInternedString;
+use syntax::symbol::Symbol;
 use syntax::source_map::{DUMMY_SP, Span};
 use crate::abi::Abi;
 
@@ -52,7 +52,7 @@
     pub vtables:
         RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>,
     /// Cache of constant strings,
-    pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'ll Value>>,
+    pub const_cstr_cache: RefCell<FxHashMap<Symbol, &'ll Value>>,
 
     /// Reverse-direction for const ptrs cast from globals.
     /// Key is a Value holding a *T,
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 928532a..d0b607b 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -2251,7 +2251,7 @@
         None
     } else {
         let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id));
-        Some(SmallCStr::new(&linkage_name.as_str()))
+        Some(SmallCStr::new(&linkage_name.name.as_str()))
     };
 
     let global_align = cx.align_of(variable_type);
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 548ea0b..6dedf10 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -32,7 +32,7 @@
 
 use libc::c_uint;
 use std::cell::RefCell;
-use std::ffi::CString;
+use std::ffi::{CStr, CString};
 
 use syntax_pos::{self, Span, Pos};
 use syntax::ast;
@@ -224,8 +224,37 @@
         gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
     }
 
-    fn set_value_name(&mut self, value: &'ll Value, name: &str) {
-        let cname = SmallCStr::new(name);
+    fn set_var_name(&mut self, value: &'ll Value, name: impl ToString) {
+        // Avoid wasting time if LLVM value names aren't even enabled.
+        if self.sess().fewer_names() {
+            return;
+        }
+
+        // Only function parameters and instructions are local to a function,
+        // don't change the name of anything else (e.g. globals).
+        let param_or_inst = unsafe {
+            llvm::LLVMIsAArgument(value).is_some() ||
+            llvm::LLVMIsAInstruction(value).is_some()
+        };
+        if !param_or_inst {
+            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 = CString::new(name.to_string()).unwrap();
         unsafe {
             llvm::LLVMSetValueName(value, cname.as_ptr());
         }
@@ -290,7 +319,7 @@
         let scope_line = span_start(self, span).line;
 
         let function_name = CString::new(name).unwrap();
-        let linkage_name = SmallCStr::new(&linkage_name.as_str());
+        let linkage_name = SmallCStr::new(&linkage_name.name.as_str());
 
         let mut flags = DIFlags::FlagPrototyped;
 
diff --git a/src/librustc_codegen_llvm/error_codes.rs b/src/librustc_codegen_llvm/error_codes.rs
index c6b5dc0..042e51e 100644
--- a/src/librustc_codegen_llvm/error_codes.rs
+++ b/src/librustc_codegen_llvm/error_codes.rs
@@ -1,4 +1,4 @@
-register_long_diagnostics! {
+register_diagnostics! {
 
 E0511: r##"
 Invalid monomorphization of an intrinsic function was used. Erroneous code
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 9483ffc..3f3c5ac1 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -15,6 +15,7 @@
 use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
+use rustc::mir::interpret::GlobalId;
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc::hir;
 use syntax::ast::{self, FloatTy};
@@ -81,13 +82,14 @@
 impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn codegen_intrinsic_call(
         &mut self,
-        callee_ty: Ty<'tcx>,
+        instance: ty::Instance<'tcx>,
         fn_ty: &FnType<'tcx, Ty<'tcx>>,
         args: &[OperandRef<'tcx, &'ll Value>],
         llresult: &'ll Value,
         span: Span,
     ) {
         let tcx = self.tcx;
+        let callee_ty = instance.ty(tcx);
 
         let (def_id, substs) = match callee_ty.sty {
             ty::FnDef(def_id, substs) => (def_id, substs),
@@ -101,7 +103,7 @@
         let name = &*tcx.item_name(def_id).as_str();
 
         let llret_ty = self.layout_of(ret_ty).llvm_type(self);
-        let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align.abi);
+        let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout);
 
         let simple = get_simple_intrinsic(self, name);
         let llval = match name {
@@ -133,10 +135,6 @@
                 let llfn = self.get_intrinsic(&("llvm.debugtrap"));
                 self.call(llfn, &[], None)
             }
-            "size_of" => {
-                let tp_ty = substs.type_at(0);
-                self.const_usize(self.size_of(tp_ty).bytes())
-            }
             "va_start" => {
                 self.va_start(args[0].immediate())
             }
@@ -188,10 +186,6 @@
                     self.const_usize(self.size_of(tp_ty).bytes())
                 }
             }
-            "min_align_of" => {
-                let tp_ty = substs.type_at(0);
-                self.const_usize(self.align_of(tp_ty).bytes())
-            }
             "min_align_of_val" => {
                 let tp_ty = substs.type_at(0);
                 if let OperandValue::Pair(_, meta) = args[0].val {
@@ -201,18 +195,19 @@
                     self.const_usize(self.align_of(tp_ty).bytes())
                 }
             }
-            "pref_align_of" => {
-                let tp_ty = substs.type_at(0);
-                self.const_usize(self.layout_of(tp_ty).align.pref.bytes())
-            }
+            "size_of" |
+            "pref_align_of" |
+            "min_align_of" |
+            "needs_drop" |
+            "type_id" |
             "type_name" => {
-                let tp_ty = substs.type_at(0);
-                let ty_name = self.tcx.type_name(tp_ty);
+                let gid = GlobalId {
+                    instance,
+                    promoted: None,
+                };
+                let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
                 OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
             }
-            "type_id" => {
-                self.const_u64(self.tcx.type_id_hash(substs.type_at(0)))
-            }
             "init" => {
                 let ty = substs.type_at(0);
                 if !self.layout_of(ty).is_zst() {
@@ -235,11 +230,6 @@
             "uninit" | "forget" => {
                 return;
             }
-            "needs_drop" => {
-                let tp_ty = substs.type_at(0);
-
-                self.const_bool(self.type_needs_drop(tp_ty))
-            }
             "offset" => {
                 let ptr = args[0].immediate();
                 let offset = args[1].immediate();
@@ -871,7 +861,7 @@
         // More information can be found in libstd's seh.rs implementation.
         let i64p = bx.type_ptr_to(bx.type_i64());
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        let slot = bx.alloca(i64p, "slot", ptr_align);
+        let slot = bx.alloca(i64p, ptr_align);
         bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
 
         normal.ret(bx.const_i32(0));
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 2fd7888..34e39af 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -14,7 +14,6 @@
 #![feature(in_band_lifetimes)]
 #![feature(libc)]
 #![feature(nll)]
-#![feature(rustc_diagnostic_macros)]
 #![feature(optin_builtin_traits)]
 #![feature(concat_idents)]
 #![feature(link_args)]
@@ -227,21 +226,21 @@
                 for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
                     println!("    {}", name);
                 }
-                println!("");
+                println!();
             }
             PrintRequest::CodeModels => {
                 println!("Available code models:");
                 for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
                     println!("    {}", name);
                 }
-                println!("");
+                println!();
             }
             PrintRequest::TlsModels => {
                 println!("Available TLS models:");
                 for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
                     println!("    {}", name);
                 }
-                println!("");
+                println!();
             }
             req => llvm_util::print(req, sess),
         }
@@ -256,7 +255,7 @@
     }
 
     fn diagnostics(&self) -> &[(&'static str, &'static str)] {
-        &DIAGNOSTICS
+        &error_codes::DIAGNOSTICS
     }
 
     fn target_features(&self, sess: &Session) -> Vec<Symbol> {
@@ -425,5 +424,3 @@
         }
     }
 }
-
-__build_diagnostic_array! { librustc_codegen_llvm, DIAGNOSTICS }
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 9f94105..b07214f 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -806,6 +806,7 @@
     pub fn LLVMRustRemoveFunctionAttributes(Fn: &Value, index: c_uint, attr: Attribute);
 
     // Operations on parameters
+    pub fn LLVMIsAArgument(Val: &Value) -> Option<&Value>;
     pub fn LLVMCountParams(Fn: &Value) -> c_uint;
     pub fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value;
 
@@ -818,6 +819,7 @@
     pub fn LLVMDeleteBasicBlock(BB: &BasicBlock);
 
     // Operations on instructions
+    pub fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>;
     pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock;
 
     // Operations on call sites
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index 89a6ec2..bc028d6 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -17,8 +17,8 @@
 log = "0.4.5"
 libc = "0.2.44"
 jobserver = "0.1.11"
-parking_lot = "0.7"
-tempfile = "3.0.5"
+parking_lot = "0.9"
+tempfile = "3.1"
 
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_codegen_ssa/back/archive.rs b/src/librustc_codegen_ssa/back/archive.rs
index 23d580e..8d2120a 100644
--- a/src/librustc_codegen_ssa/back/archive.rs
+++ b/src/librustc_codegen_ssa/back/archive.rs
@@ -1,9 +1,10 @@
 use rustc::session::Session;
+use syntax::symbol::Symbol;
 
 use std::io;
 use std::path::{Path, PathBuf};
 
-pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session)
+pub fn find_library(name: Symbol, search_paths: &[PathBuf], sess: &Session)
                     -> PathBuf {
     // On Windows, static libraries sometimes show up as libfoo.a and other
     // times show up as foo.lib
@@ -40,7 +41,7 @@
         lto: bool,
         skip_objects: bool,
     ) -> io::Result<()>;
-    fn add_native_library(&mut self, name: &str);
+    fn add_native_library(&mut self, name: Symbol);
     fn update_symbols(&mut self);
 
     fn build(self);
diff --git a/src/librustc_codegen_ssa/back/command.rs b/src/librustc_codegen_ssa/back/command.rs
index 340cc77..2d84d67 100644
--- a/src/librustc_codegen_ssa/back/command.rs
+++ b/src/librustc_codegen_ssa/back/command.rs
@@ -8,12 +8,14 @@
 use std::process::{self, Output};
 
 use rustc_target::spec::LldFlavor;
+use syntax::symbol::Symbol;
 
 #[derive(Clone)]
 pub struct Command {
     program: Program,
     args: Vec<OsString>,
     env: Vec<(OsString, OsString)>,
+    env_remove: Vec<OsString>,
 }
 
 #[derive(Clone)]
@@ -41,6 +43,7 @@
             program,
             args: Vec::new(),
             env: Vec::new(),
+            env_remove: Vec::new(),
         }
     }
 
@@ -49,6 +52,11 @@
         self
     }
 
+    pub fn sym_arg(&mut self, arg: Symbol) -> &mut Command {
+        self.arg(&arg.as_str());
+        self
+    }
+
     pub fn args<I>(&mut self, args: I) -> &mut Command
     where
         I: IntoIterator<Item: AsRef<OsStr>>,
@@ -75,6 +83,17 @@
         self.env.push((key.to_owned(), value.to_owned()));
     }
 
+    pub fn env_remove<K>(&mut self, key: K) -> &mut Command
+        where K: AsRef<OsStr>,
+    {
+        self._env_remove(key.as_ref());
+        self
+    }
+
+    fn _env_remove(&mut self, key: &OsStr) {
+        self.env_remove.push(key.to_owned());
+    }
+
     pub fn output(&mut self) -> io::Result<Output> {
         self.command().output()
     }
@@ -100,6 +119,9 @@
         };
         ret.args(&self.args);
         ret.envs(self.env.clone());
+        for k in &self.env_remove {
+            ret.env_remove(k);
+        }
         return ret
     }
 
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 8603d61..9b044d9 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -13,6 +13,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
 use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor};
+use syntax::symbol::Symbol;
 
 use crate::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION, CrateInfo, CodegenResults};
 use super::archive::ArchiveBuilder;
@@ -316,7 +317,7 @@
             NativeLibraryKind::NativeUnknown => continue,
         }
         if let Some(name) = lib.name {
-            ab.add_native_library(&name.as_str());
+            ab.add_native_library(name);
         }
     }
 
@@ -532,6 +533,9 @@
     for &(ref k, ref v) in &sess.target.target.options.link_env {
         cmd.env(k, v);
     }
+    for k in &sess.target.target.options.link_env_remove {
+        cmd.env_remove(k);
+    }
 
     if sess.opts.debugging_opts.print_link_args {
         println!("{:?}", &cmd);
@@ -1273,15 +1277,14 @@
     let search_path = archive_search_paths(sess);
     for lib in relevant_libs {
         let name = match lib.name {
-            Some(ref l) => l,
+            Some(l) => l,
             None => continue,
         };
         match lib.kind {
-            NativeLibraryKind::NativeUnknown => cmd.link_dylib(&name.as_str()),
-            NativeLibraryKind::NativeFramework => cmd.link_framework(&name.as_str()),
-            NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&name.as_str()),
-            NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(&name.as_str(),
-                                                                        &search_path)
+            NativeLibraryKind::NativeUnknown => cmd.link_dylib(name),
+            NativeLibraryKind::NativeFramework => cmd.link_framework(name),
+            NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(name),
+            NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(name, &search_path)
         }
     }
 }
@@ -1594,7 +1597,7 @@
             cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
         }
         let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
-        cmd.link_rust_dylib(&unlib(&sess.target, filestem),
+        cmd.link_rust_dylib(Symbol::intern(&unlib(&sess.target, filestem)),
                             parent.unwrap_or(Path::new("")));
     }
 }
@@ -1637,22 +1640,22 @@
     for &(cnum, _) in crates {
         for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
             let name = match lib.name {
-                Some(ref l) => l,
+                Some(l) => l,
                 None => continue,
             };
             if !relevant_lib(sess, &lib) {
                 continue
             }
             match lib.kind {
-                NativeLibraryKind::NativeUnknown => cmd.link_dylib(&name.as_str()),
-                NativeLibraryKind::NativeFramework => cmd.link_framework(&name.as_str()),
+                NativeLibraryKind::NativeUnknown => cmd.link_dylib(name),
+                NativeLibraryKind::NativeFramework => cmd.link_framework(name),
                 NativeLibraryKind::NativeStaticNobundle => {
                     // Link "static-nobundle" native libs only if the crate they originate from
                     // is being linked statically to the current crate.  If it's linked dynamically
                     // or is an rlib already included via some other dylib crate, the symbols from
                     // native libs will have already been included in that dylib.
                     if data[cnum.as_usize() - 1] == Linkage::Static {
-                        cmd.link_staticlib(&name.as_str())
+                        cmd.link_staticlib(name)
                     }
                 },
                 // ignore statically included native libraries here as we've
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index de481d2..c42cd02 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -17,6 +17,7 @@
 use rustc::ty::TyCtxt;
 use rustc_target::spec::{LinkerFlavor, LldFlavor};
 use rustc_serialize::{json, Encoder};
+use syntax::symbol::Symbol;
 
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
@@ -99,13 +100,13 @@
 /// used to dispatch on whether a GNU-like linker (generally `ld.exe`) or an
 /// MSVC linker (e.g., `link.exe`) is being used.
 pub trait Linker {
-    fn link_dylib(&mut self, lib: &str);
-    fn link_rust_dylib(&mut self, lib: &str, path: &Path);
-    fn link_framework(&mut self, framework: &str);
-    fn link_staticlib(&mut self, lib: &str);
+    fn link_dylib(&mut self, lib: Symbol);
+    fn link_rust_dylib(&mut self, lib: Symbol, path: &Path);
+    fn link_framework(&mut self, framework: Symbol);
+    fn link_staticlib(&mut self, lib: Symbol);
     fn link_rlib(&mut self, lib: &Path);
     fn link_whole_rlib(&mut self, lib: &Path);
-    fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]);
+    fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]);
     fn include_path(&mut self, path: &Path);
     fn framework_path(&mut self, path: &Path);
     fn output_filename(&mut self, path: &Path);
@@ -215,9 +216,13 @@
 }
 
 impl<'a> Linker for GccLinker<'a> {
-    fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg(format!("-l{}", lib)); }
-    fn link_staticlib(&mut self, lib: &str) {
-        self.hint_static(); self.cmd.arg(format!("-l{}", lib));
+    fn link_dylib(&mut self, lib: Symbol) {
+        self.hint_dynamic();
+        self.cmd.arg(format!("-l{}", lib));
+    }
+    fn link_staticlib(&mut self, lib: Symbol) {
+        self.hint_static();
+        self.cmd.arg(format!("-l{}", lib));
     }
     fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
     fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); }
@@ -232,14 +237,14 @@
     fn build_static_executable(&mut self) { self.cmd.arg("-static"); }
     fn args(&mut self, args: &[String]) { self.cmd.args(args); }
 
-    fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+    fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
         self.hint_dynamic();
         self.cmd.arg(format!("-l{}", lib));
     }
 
-    fn link_framework(&mut self, framework: &str) {
+    fn link_framework(&mut self, framework: Symbol) {
         self.hint_dynamic();
-        self.cmd.arg("-framework").arg(framework);
+        self.cmd.arg("-framework").sym_arg(framework);
     }
 
     // Here we explicitly ask that the entire archive is included into the
@@ -248,7 +253,7 @@
     // don't otherwise explicitly reference them. This can occur for
     // libraries which are just providing bindings, libraries with generic
     // functions, etc.
-    fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) {
+    fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]) {
         self.hint_static();
         let target = &self.sess.target.target;
         if !target.options.is_like_osx {
@@ -539,11 +544,11 @@
         }
     }
 
-    fn link_dylib(&mut self, lib: &str) {
+    fn link_dylib(&mut self, lib: Symbol) {
         self.cmd.arg(&format!("{}.lib", lib));
     }
 
-    fn link_rust_dylib(&mut self, lib: &str, path: &Path) {
+    fn link_rust_dylib(&mut self, lib: Symbol, path: &Path) {
         // When producing a dll, the MSVC linker may not actually emit a
         // `foo.lib` file if the dll doesn't actually export any symbols, so we
         // check to see if the file is there and just omit linking to it if it's
@@ -554,7 +559,7 @@
         }
     }
 
-    fn link_staticlib(&mut self, lib: &str) {
+    fn link_staticlib(&mut self, lib: Symbol) {
         self.cmd.arg(&format!("{}.lib", lib));
     }
 
@@ -605,11 +610,11 @@
     fn framework_path(&mut self, _path: &Path) {
         bug!("frameworks are not supported on windows")
     }
-    fn link_framework(&mut self, _framework: &str) {
+    fn link_framework(&mut self, _framework: Symbol) {
         bug!("frameworks are not supported on windows")
     }
 
-    fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
+    fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
         // not supported?
         self.link_staticlib(lib);
     }
@@ -740,8 +745,8 @@
         self.cmd.arg("-L").arg(path);
     }
 
-    fn link_staticlib(&mut self, lib: &str) {
-        self.cmd.arg("-l").arg(lib);
+    fn link_staticlib(&mut self, lib: Symbol) {
+        self.cmd.arg("-l").sym_arg(lib);
     }
 
     fn output_filename(&mut self, path: &Path) {
@@ -752,12 +757,12 @@
         self.cmd.arg(path);
     }
 
-    fn link_dylib(&mut self, lib: &str) {
+    fn link_dylib(&mut self, lib: Symbol) {
         // Emscripten always links statically
         self.link_staticlib(lib);
     }
 
-    fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
+    fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
         // not supported?
         self.link_staticlib(lib);
     }
@@ -767,7 +772,7 @@
         self.link_rlib(lib);
     }
 
-    fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+    fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
         self.link_dylib(lib);
     }
 
@@ -803,7 +808,7 @@
         bug!("frameworks are not supported on Emscripten")
     }
 
-    fn link_framework(&mut self, _framework: &str) {
+    fn link_framework(&mut self, _framework: Symbol) {
         bug!("frameworks are not supported on Emscripten")
     }
 
@@ -948,12 +953,12 @@
 }
 
 impl<'a> Linker for WasmLd<'a> {
-    fn link_dylib(&mut self, lib: &str) {
-        self.cmd.arg("-l").arg(lib);
+    fn link_dylib(&mut self, lib: Symbol) {
+        self.cmd.arg("-l").sym_arg(lib);
     }
 
-    fn link_staticlib(&mut self, lib: &str) {
-        self.cmd.arg("-l").arg(lib);
+    fn link_staticlib(&mut self, lib: Symbol) {
+        self.cmd.arg("-l").sym_arg(lib);
     }
 
     fn link_rlib(&mut self, lib: &Path) {
@@ -995,16 +1000,16 @@
         self.cmd.args(args);
     }
 
-    fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
-        self.cmd.arg("-l").arg(lib);
+    fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
+        self.cmd.arg("-l").sym_arg(lib);
     }
 
-    fn link_framework(&mut self, _framework: &str) {
+    fn link_framework(&mut self, _framework: Symbol) {
         panic!("frameworks not supported")
     }
 
-    fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
-        self.cmd.arg("-l").arg(lib);
+    fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
+        self.cmd.arg("-l").sym_arg(lib);
     }
 
     fn link_whole_rlib(&mut self, lib: &Path) {
@@ -1162,19 +1167,19 @@
         ::std::mem::replace(&mut self.cmd, Command::new(""))
     }
 
-    fn link_dylib(&mut self, _lib: &str) {
+    fn link_dylib(&mut self, _lib: Symbol) {
         panic!("external dylibs not supported")
     }
 
-    fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) {
+    fn link_rust_dylib(&mut self, _lib: Symbol, _path: &Path) {
         panic!("external dylibs not supported")
     }
 
-    fn link_staticlib(&mut self, _lib: &str) {
+    fn link_staticlib(&mut self, _lib: Symbol) {
         panic!("staticlibs not supported")
     }
 
-    fn link_whole_staticlib(&mut self, _lib: &str, _search_path: &[PathBuf]) {
+    fn link_whole_staticlib(&mut self, _lib: Symbol, _search_path: &[PathBuf]) {
         panic!("staticlibs not supported")
     }
 
@@ -1182,7 +1187,7 @@
         panic!("frameworks not supported")
     }
 
-    fn link_framework(&mut self, _framework: &str) {
+    fn link_framework(&mut self, _framework: Symbol) {
         panic!("frameworks not supported")
     }
 
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 2d9220f..7e700e6 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -121,7 +121,7 @@
         })
         .map(|def_id| {
             let export_level = if special_runtime_crate {
-                let name = tcx.symbol_name(Instance::mono(tcx, def_id)).as_str();
+                let name = tcx.symbol_name(Instance::mono(tcx, def_id)).name.as_str();
                 // We can probably do better here by just ensuring that
                 // it has hidden visibility rather than public
                 // visibility, as this is primarily here to ensure it's
diff --git a/src/librustc_codegen_ssa/error_codes.rs b/src/librustc_codegen_ssa/error_codes.rs
index 8d46dcb..8ff41c2 100644
--- a/src/librustc_codegen_ssa/error_codes.rs
+++ b/src/librustc_codegen_ssa/error_codes.rs
@@ -1,4 +1,4 @@
-register_long_diagnostics! {
+syntax::register_diagnostics! {
 
 E0668: r##"
 Malformed inline assembly rejected by LLVM.
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 68640ab..1708d72 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -4,7 +4,7 @@
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
 #![feature(libc)]
-#![feature(rustc_diagnostic_macros)]
+#![feature(slice_patterns)]
 #![feature(stmt_expr_attributes)]
 #![feature(try_blocks)]
 #![feature(in_band_lifetimes)]
@@ -35,8 +35,6 @@
 use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary};
 use syntax_pos::symbol::Symbol;
 
-// N.B., this module needs to be declared first so diagnostics are
-// registered before they are used.
 mod error_codes;
 
 pub mod common;
@@ -158,5 +156,3 @@
     pub linker_info: back::linker::LinkerInfo,
     pub crate_info: CrateInfo,
 }
-
-__build_diagnostic_array! { librustc_codegen_ssa, DIAGNOSTICS }
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index e63f1b9..d192f2f 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -105,7 +105,7 @@
     ) {
         let cx = self.fx.cx;
 
-        if let Some(proj) = place_ref.projection {
+        if let [proj_base @ .., elem] = place_ref.projection {
             // Allow uses of projections that are ZSTs or from scalar fields.
             let is_consume = match context {
                 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
@@ -114,12 +114,12 @@
             };
             if is_consume {
                 let base_ty =
-                    mir::Place::ty_from(place_ref.base, &proj.base, self.fx.mir, cx.tcx());
+                    mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir, cx.tcx());
                 let base_ty = self.fx.monomorphize(&base_ty);
 
                 // ZSTs don't require any actual memory access.
                 let elem_ty = base_ty
-                    .projection_ty(cx.tcx(), &proj.elem)
+                    .projection_ty(cx.tcx(), elem)
                     .ty;
                 let elem_ty = self.fx.monomorphize(&elem_ty);
                 let span = if let mir::PlaceBase::Local(index) = place_ref.base {
@@ -131,7 +131,7 @@
                     return;
                 }
 
-                if let mir::ProjectionElem::Field(..) = proj.elem {
+                if let mir::ProjectionElem::Field(..) = elem {
                     let layout = cx.spanned_layout_of(base_ty.ty, span);
                     if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
                         // Recurse with the same context, instead of `Projection`,
@@ -140,7 +140,7 @@
                         self.process_place(
                             &mir::PlaceRef {
                                 base: place_ref.base,
-                                projection: &proj.base,
+                                projection: proj_base,
                             },
                             context,
                             location,
@@ -151,11 +151,11 @@
             }
 
             // A deref projection only reads the pointer, never needs the place.
-            if let mir::ProjectionElem::Deref = proj.elem {
+            if let mir::ProjectionElem::Deref = elem {
                 self.process_place(
                     &mir::PlaceRef {
                         base: place_ref.base,
-                        projection: &proj.base,
+                        projection: proj_base,
                     },
                     PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
                     location
@@ -168,7 +168,7 @@
         // visit_place API
         let mut context = context;
 
-        if place_ref.projection.is_some() {
+        if !place_ref.projection.is_empty() {
             context = if context.is_mutating_use() {
                 PlaceContext::MutatingUse(MutatingUseContext::Projection)
             } else {
@@ -177,10 +177,7 @@
         }
 
         self.visit_place_base(place_ref.base, context, location);
-
-        if let Some(box proj) = place_ref.projection {
-            self.visit_projection(place_ref.base, proj, context, location);
-        }
+        self.visit_projection(place_ref.base, place_ref.projection, context, location);
     }
 
 }
@@ -196,7 +193,7 @@
 
         if let mir::Place {
             base: mir::PlaceBase::Local(index),
-            projection: None,
+            projection: box [],
         } = *place {
             self.assign(index, location);
             let decl_span = self.fx.mir.local_decls[index].source_info.span;
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index d2a7571..1bb0ea5 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -14,7 +14,7 @@
 
 use std::borrow::Cow;
 
-use syntax::symbol::LocalInternedString;
+use syntax::symbol::Symbol;
 use syntax_pos::Pos;
 
 use super::{FunctionCx, LocalRef};
@@ -253,7 +253,7 @@
 
             PassMode::Direct(_) | PassMode::Pair(..) => {
                 let op =
-                    self.codegen_consume(&mut bx, &mir::Place::RETURN_PLACE.as_ref());
+                    self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref());
                 if let Ref(llval, _, align) = op.val {
                     bx.load(llval, align)
                 } else {
@@ -276,7 +276,7 @@
                 let llslot = match op.val {
                     Immediate(_) | Pair(..) => {
                         let scratch =
-                            PlaceRef::alloca(&mut bx, self.fn_ty.ret.layout, "ret");
+                            PlaceRef::alloca(&mut bx, self.fn_ty.ret.layout);
                         op.val.store(&mut bx, scratch);
                         scratch.llval
                     }
@@ -397,7 +397,7 @@
 
         // Get the location information.
         let loc = bx.sess().source_map().lookup_char_pos(span.lo());
-        let filename = LocalInternedString::intern(&loc.file.name.to_string());
+        let filename = Symbol::intern(&loc.file.name.to_string());
         let line = bx.const_u32(loc.line as u32);
         let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
 
@@ -418,8 +418,7 @@
                     vec![file_line_col, index, len])
             }
             _ => {
-                let str = msg.description();
-                let msg_str = LocalInternedString::intern(str);
+                let msg_str = Symbol::intern(msg.description());
                 let msg_file_line_col = bx.static_panic_msg(
                     Some(msg_str),
                     filename,
@@ -531,7 +530,7 @@
             let layout = bx.layout_of(ty);
             if layout.abi.is_uninhabited() {
                 let loc = bx.sess().source_map().lookup_char_pos(span.lo());
-                let filename = LocalInternedString::intern(&loc.file.name.to_string());
+                let filename = Symbol::intern(&loc.file.name.to_string());
                 let line = bx.const_u32(loc.line as u32);
                 let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
 
@@ -539,7 +538,7 @@
                     "Attempted to instantiate uninhabited type {}",
                     ty
                 );
-                let msg_str = LocalInternedString::intern(&str);
+                let msg_str = Symbol::intern(&str);
                 let msg_file_line_col = bx.static_panic_msg(
                     Some(msg_str),
                     filename,
@@ -613,7 +612,7 @@
                                     ty,
                                     def_id: _,
                                 }),
-                                projection: None,
+                                projection: box [],
                             }
                         ) |
                         mir::Operand::Move(
@@ -623,7 +622,7 @@
                                     ty,
                                     def_id: _,
                                 }),
-                                projection: None,
+                                projection: box [],
                             }
                         ) => {
                             let param_env = ty::ParamEnv::reveal_all();
@@ -668,8 +667,7 @@
             }).collect();
 
 
-            let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
-            bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
+            bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest,
                                       terminator.source_info.span);
 
             if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
@@ -768,7 +766,7 @@
             match (arg, op.val) {
                 (&mir::Operand::Copy(_), Ref(_, None, _)) |
                 (&mir::Operand::Constant(_), Ref(_, None, _)) => {
-                    let tmp = PlaceRef::alloca(&mut bx, op.layout, "const");
+                    let tmp = PlaceRef::alloca(&mut bx, op.layout);
                     op.val.store(&mut bx, tmp);
                     op.val = Ref(tmp.llval, None, tmp.align);
                 }
@@ -926,7 +924,7 @@
             Immediate(_) | Pair(..) => {
                 match arg.mode {
                     PassMode::Indirect(..) | PassMode::Cast(_) => {
-                        let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
+                        let scratch = PlaceRef::alloca(bx, arg.layout);
                         op.val.store(bx, scratch);
                         (scratch.llval, scratch.align, true)
                     }
@@ -941,7 +939,7 @@
                     // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't
                     // have scary latent bugs around.
 
-                    let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
+                    let scratch = PlaceRef::alloca(bx, arg.layout);
                     base::memcpy_ty(bx, scratch.llval, scratch.align, llval, align,
                                     op.layout, MemFlags::empty());
                     (scratch.llval, scratch.align, true)
@@ -989,7 +987,7 @@
 
         // Handle both by-ref and immediate tuples.
         if let Ref(llval, None, align) = tuple.val {
-            let tuple_ptr = PlaceRef::new_sized(llval, tuple.layout, align);
+            let tuple_ptr = PlaceRef::new_sized_aligned(llval, tuple.layout, align);
             for i in 0..tuple.layout.fields.count() {
                 let field_ptr = tuple_ptr.project_field(bx, i);
                 let field = bx.load_operand(field_ptr);
@@ -1018,7 +1016,7 @@
                 cx.tcx().mk_mut_ptr(cx.tcx().types.u8),
                 cx.tcx().types.i32
             ]));
-            let slot = PlaceRef::alloca(bx, layout, "personalityslot");
+            let slot = PlaceRef::alloca(bx, layout);
             self.personality_slot = Some(slot);
             slot
         }
@@ -1106,7 +1104,7 @@
         }
         let dest = if let mir::Place {
             base: mir::PlaceBase::Local(index),
-            projection: None,
+            projection: box [],
         } = *dest {
             match self.locals[index] {
                 LocalRef::Place(dest) => dest,
@@ -1117,7 +1115,7 @@
                     return if fn_ret.is_indirect() {
                         // Odd, but possible, case, we have an operand temporary,
                         // but the calling convention has an indirect return.
-                        let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret");
+                        let tmp = PlaceRef::alloca(bx, fn_ret.layout);
                         tmp.storage_live(bx);
                         llargs.push(tmp.llval);
                         ReturnDest::IndirectOperand(tmp, index)
@@ -1125,7 +1123,7 @@
                         // Currently, intrinsics always need a location to store
                         // the result, so we create a temporary `alloca` for the
                         // result.
-                        let tmp = PlaceRef::alloca(bx, fn_ret.layout, "tmp_ret");
+                        let tmp = PlaceRef::alloca(bx, fn_ret.layout);
                         tmp.storage_live(bx);
                         ReturnDest::IndirectOperand(tmp, index)
                     } else {
@@ -1167,7 +1165,7 @@
     ) {
         if let mir::Place {
             base: mir::PlaceBase::Local(index),
-            projection: None,
+            projection: box [],
         } = *dst {
             match self.locals[index] {
                 LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
@@ -1175,7 +1173,7 @@
                 LocalRef::Operand(None) => {
                     let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref()));
                     assert!(!dst_layout.ty.has_erasable_regions());
-                    let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp");
+                    let place = PlaceRef::alloca(bx, dst_layout);
                     place.storage_live(bx);
                     self.codegen_transmute_into(bx, src, place);
                     let op = bx.load_operand(place);
@@ -1203,7 +1201,7 @@
         let llty = bx.backend_type(src.layout);
         let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty));
         let align = src.layout.align.abi.min(dst.align);
-        src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align));
+        src.val.store(bx, PlaceRef::new_sized_aligned(cast_ptr, src.layout, align));
     }
 
 
@@ -1228,7 +1226,7 @@
             DirectOperand(index) => {
                 // If there is a cast, we have to store and reload.
                 let op = if let PassMode::Cast(_) = ret_ty.mode {
-                    let tmp = PlaceRef::alloca(bx, ret_ty.layout, "tmp_ret");
+                    let tmp = PlaceRef::alloca(bx, ret_ty.layout);
                     tmp.storage_live(bx);
                     bx.store_arg_ty(&ret_ty, llval, tmp);
                     let op = bx.load_operand(tmp);
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 32bcdeb..aa3971a 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -268,11 +268,13 @@
                 debug!("alloc: {:?} ({}) -> place", local, name);
                 if layout.is_unsized() {
                     let indirect_place =
-                        PlaceRef::alloca_unsized_indirect(&mut bx, layout, &name.as_str());
+                        PlaceRef::alloca_unsized_indirect(&mut bx, layout);
+                    bx.set_var_name(indirect_place.llval, name);
                     // FIXME: add an appropriate debuginfo
                     LocalRef::UnsizedPlace(indirect_place)
                 } else {
-                    let place = PlaceRef::alloca(&mut bx, layout, &name.as_str());
+                    let place = PlaceRef::alloca(&mut bx, layout);
+                    bx.set_var_name(place.llval, name);
                     if dbg {
                         let (scope, span) = fx.debug_loc(mir::SourceInfo {
                             span: decl.source_info.span,
@@ -289,18 +291,17 @@
                 if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() {
                     debug!("alloc: {:?} (return place) -> place", local);
                     let llretptr = bx.get_param(0);
-                    LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align.abi))
+                    LocalRef::Place(PlaceRef::new_sized(llretptr, layout))
                 } else if memory_locals.contains(local) {
                     debug!("alloc: {:?} -> place", local);
                     if layout.is_unsized() {
-                        let indirect_place = PlaceRef::alloca_unsized_indirect(
-                            &mut bx,
-                            layout,
-                            &format!("{:?}", local),
-                        );
+                        let indirect_place = PlaceRef::alloca_unsized_indirect(&mut bx, layout);
+                        bx.set_var_name(indirect_place.llval, format_args!("{:?}", local));
                         LocalRef::UnsizedPlace(indirect_place)
                     } else {
-                        LocalRef::Place(PlaceRef::alloca(&mut bx, layout, &format!("{:?}", local)))
+                        let place = PlaceRef::alloca(&mut bx, layout);
+                        bx.set_var_name(place.llval, format_args!("{:?}", local));
+                        LocalRef::Place(place)
                     }
                 } else {
                     // If this is an immediate local, we do not create an
@@ -452,10 +453,11 @@
     mir.args_iter().enumerate().map(|(arg_index, local)| {
         let arg_decl = &mir.local_decls[local];
 
+        // FIXME(eddyb) don't allocate a `String` unless it gets used.
         let name = if let Some(name) = arg_decl.name {
             name.as_str().to_string()
         } else {
-            format!("arg{}", arg_index)
+            format!("{:?}", local)
         };
 
         if Some(local) == mir.spread_arg {
@@ -470,7 +472,8 @@
                 _ => bug!("spread argument isn't a tuple?!")
             };
 
-            let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty), &name);
+            let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
+            bx.set_var_name(place.llval, name);
             for i in 0..tupled_arg_tys.len() {
                 let arg = &fx.fn_ty.args[idx];
                 idx += 1;
@@ -518,19 +521,19 @@
                 PassMode::Ignore(IgnoreMode::CVarArgs) => {}
                 PassMode::Direct(_) => {
                     let llarg = bx.get_param(llarg_idx);
-                    bx.set_value_name(llarg, &name);
+                    bx.set_var_name(llarg, &name);
                     llarg_idx += 1;
                     return local(
                         OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
                 }
                 PassMode::Pair(..) => {
-                    let a = bx.get_param(llarg_idx);
-                    bx.set_value_name(a, &(name.clone() + ".0"));
-                    llarg_idx += 1;
+                    let (a, b) = (bx.get_param(llarg_idx), bx.get_param(llarg_idx + 1));
+                    llarg_idx += 2;
 
-                    let b = bx.get_param(llarg_idx);
-                    bx.set_value_name(b, &(name + ".1"));
-                    llarg_idx += 1;
+                    // FIXME(eddyb) these are scalar components,
+                    // maybe extract the high-level fields?
+                    bx.set_var_name(a, format_args!("{}.0", name));
+                    bx.set_var_name(b, format_args!("{}.1", name));
 
                     return local(OperandRef {
                         val: OperandValue::Pair(a, b),
@@ -546,9 +549,9 @@
             // already put it in a temporary alloca and gave it up.
             // FIXME: lifetimes
             let llarg = bx.get_param(llarg_idx);
-            bx.set_value_name(llarg, &name);
+            bx.set_var_name(llarg, &name);
             llarg_idx += 1;
-            PlaceRef::new_sized(llarg, arg.layout, arg.layout.align.abi)
+            PlaceRef::new_sized(llarg, arg.layout)
         } else if arg.is_unsized_indirect() {
             // As the storage for the indirect argument lives during
             // the whole function call, we just copy the fat pointer.
@@ -558,11 +561,13 @@
             llarg_idx += 1;
             let indirect_operand = OperandValue::Pair(llarg, llextra);
 
-            let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout, &name);
+            let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout);
+            bx.set_var_name(tmp.llval, name);
             indirect_operand.store(bx, tmp);
             tmp
         } else {
-            let tmp = PlaceRef::alloca(bx, arg.layout, &name);
+            let tmp = PlaceRef::alloca(bx, arg.layout);
+            bx.set_var_name(tmp.llval, name);
             if fx.fn_ty.c_variadic && last_arg_idx.map(|idx| arg_index == idx).unwrap_or(false) {
                 let va_list_did = match tcx.lang_items().va_list() {
                     Some(did) => did,
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 254b73d..daa25b2 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -367,7 +367,7 @@
 
         // Allocate an appropriate region on the stack, and copy the value into it
         let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
-        let lldst = bx.array_alloca(bx.cx().type_i8(), llsize, "unsized_tmp", max_align);
+        let lldst = bx.array_alloca(bx.cx().type_i8(), llsize, max_align);
         bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags);
 
         // Store the allocated region and the extra to the indirect place.
@@ -384,47 +384,45 @@
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
         debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
 
-        place_ref.iterate(|place_base, place_projection| {
-            if let mir::PlaceBase::Local(index) = place_base {
-                match self.locals[*index] {
-                    LocalRef::Operand(Some(mut o)) => {
-                        // Moves out of scalar and scalar pair fields are trivial.
-                        for proj in place_projection {
-                            match proj.elem {
-                                mir::ProjectionElem::Field(ref f, _) => {
-                                    o = o.extract_field(bx, f.index());
-                                }
-                                mir::ProjectionElem::Index(_) |
-                                mir::ProjectionElem::ConstantIndex { .. } => {
-                                    // ZSTs don't require any actual memory access.
-                                    // FIXME(eddyb) deduplicate this with the identical
-                                    // checks in `codegen_consume` and `extract_field`.
-                                    let elem = o.layout.field(bx.cx(), 0);
-                                    if elem.is_zst() {
-                                        o = OperandRef::new_zst(bx, elem);
-                                    } else {
-                                        return None;
-                                    }
-                                }
-                                _ => return None,
+        if let mir::PlaceBase::Local(index) = place_ref.base {
+            match self.locals[*index] {
+                LocalRef::Operand(Some(mut o)) => {
+                    // Moves out of scalar and scalar pair fields are trivial.
+                    for elem in place_ref.projection.iter() {
+                        match elem {
+                            mir::ProjectionElem::Field(ref f, _) => {
+                                o = o.extract_field(bx, f.index());
                             }
+                            mir::ProjectionElem::Index(_) |
+                            mir::ProjectionElem::ConstantIndex { .. } => {
+                                // ZSTs don't require any actual memory access.
+                                // FIXME(eddyb) deduplicate this with the identical
+                                // checks in `codegen_consume` and `extract_field`.
+                                let elem = o.layout.field(bx.cx(), 0);
+                                if elem.is_zst() {
+                                    o = OperandRef::new_zst(bx, elem);
+                                } else {
+                                    return None;
+                                }
+                            }
+                            _ => return None,
                         }
+                    }
 
-                        Some(o)
-                    }
-                    LocalRef::Operand(None) => {
-                        bug!("use of {:?} before def", place_ref);
-                    }
-                    LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
-                        // watch out for locals that do not have an
-                        // alloca; they are handled somewhat differently
-                        None
-                    }
+                    Some(o)
                 }
-            } else {
-                None
+                LocalRef::Operand(None) => {
+                    bug!("use of {:?} before def", place_ref);
+                }
+                LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
+                    // watch out for locals that do not have an
+                    // alloca; they are handled somewhat differently
+                    None
+                }
             }
-        })
+        } else {
+            None
+        }
     }
 
     pub fn codegen_consume(
@@ -485,7 +483,6 @@
                         bx.load_operand(PlaceRef::new_sized(
                             bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))),
                             layout,
-                            layout.align.abi,
                         ))
                     })
             }
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index ac72928..a4b4cb5 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -30,6 +30,19 @@
     pub fn new_sized(
         llval: V,
         layout: TyLayout<'tcx>,
+    ) -> PlaceRef<'tcx, V> {
+        assert!(!layout.is_unsized());
+        PlaceRef {
+            llval,
+            llextra: None,
+            layout,
+            align: layout.align.abi
+        }
+    }
+
+    pub fn new_sized_aligned(
+        llval: V,
+        layout: TyLayout<'tcx>,
         align: Align,
     ) -> PlaceRef<'tcx, V> {
         assert!(!layout.is_unsized());
@@ -45,39 +58,34 @@
         bx: &mut Bx,
         llval: V,
         layout: TyLayout<'tcx>,
-        align: Align,
     ) -> PlaceRef<'tcx, V> {
         assert!(!bx.cx().type_has_metadata(layout.ty));
         PlaceRef {
             llval,
             llextra: None,
             layout,
-            align
+            align: layout.align.abi
         }
     }
 
     pub fn alloca<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
         layout: TyLayout<'tcx>,
-        name: &str
     ) -> Self {
-        debug!("alloca({:?}: {:?})", name, layout);
         assert!(!layout.is_unsized(), "tried to statically allocate unsized place");
-        let tmp = bx.alloca(bx.cx().backend_type(layout), name, layout.align.abi);
-        Self::new_sized(tmp, layout, layout.align.abi)
+        let tmp = bx.alloca(bx.cx().backend_type(layout), layout.align.abi);
+        Self::new_sized(tmp, layout)
     }
 
     /// Returns a place for an indirect reference to an unsized place.
     pub fn alloca_unsized_indirect<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
         layout: TyLayout<'tcx>,
-        name: &str,
     ) -> Self {
-        debug!("alloca_unsized_indirect({:?}: {:?})", name, layout);
         assert!(layout.is_unsized(), "tried to allocate indirect place for sized values");
         let ptr_ty = bx.cx().tcx().mk_mut_ptr(layout.ty);
         let ptr_layout = bx.cx().layout_of(ptr_ty);
-        Self::alloca(bx, ptr_layout, name)
+        Self::alloca(bx, ptr_layout)
     }
 
     pub fn len<Cx: ConstMethods<'tcx, Value = V>>(
@@ -437,7 +445,7 @@
         let result = match &place_ref {
             mir::PlaceRef {
                 base: mir::PlaceBase::Local(index),
-                projection: None,
+                projection: [],
             } => {
                 match self.locals[*index] {
                     LocalRef::Place(place) => {
@@ -457,7 +465,7 @@
                     kind: mir::StaticKind::Promoted(promoted, substs),
                     def_id,
                 }),
-                projection: None,
+                projection: [],
             } => {
                 let param_env = ty::ParamEnv::reveal_all();
                 let instance = Instance::new(*def_id, self.monomorphize(substs));
@@ -482,7 +490,7 @@
                         let llval = bx.cx().const_undef(
                             bx.cx().type_ptr_to(bx.cx().backend_type(layout))
                         );
-                        PlaceRef::new_sized(llval, layout, layout.align.abi)
+                        PlaceRef::new_sized(llval, layout)
                     }
                 }
             }
@@ -492,20 +500,17 @@
                     kind: mir::StaticKind::Static,
                     def_id,
                 }),
-                projection: None,
+                projection: [],
             } => {
                 // NB: The layout of a static may be unsized as is the case when working
                 // with a static that is an extern_type.
                 let layout = cx.layout_of(self.monomorphize(&ty));
                 let static_ = bx.get_static(*def_id);
-                PlaceRef::new_thin_place(bx, static_, layout, layout.align.abi)
+                PlaceRef::new_thin_place(bx, static_, layout)
             },
             mir::PlaceRef {
                 base,
-                projection: Some(box mir::Projection {
-                    base: proj_base,
-                    elem: mir::ProjectionElem::Deref,
-                }),
+                projection: [proj_base @ .., mir::ProjectionElem::Deref],
             } => {
                 // Load the pointer from its location.
                 self.codegen_consume(bx, &mir::PlaceRef {
@@ -515,22 +520,22 @@
             }
             mir::PlaceRef {
                 base,
-                projection: Some(projection),
+                projection: [proj_base @ .., elem],
             } => {
                 // FIXME turn this recursion into iteration
                 let cg_base = self.codegen_place(bx, &mir::PlaceRef {
                     base,
-                    projection: &projection.base,
+                    projection: proj_base,
                 });
 
-                match projection.elem {
+                match elem {
                     mir::ProjectionElem::Deref => bug!(),
                     mir::ProjectionElem::Field(ref field, _) => {
                         cg_base.project_field(bx, field.index())
                     }
                     mir::ProjectionElem::Index(index) => {
                         let index = &mir::Operand::Copy(
-                            mir::Place::from(index)
+                            mir::Place::from(*index)
                         );
                         let index = self.codegen_operand(bx, index);
                         let llindex = index.immediate();
@@ -539,27 +544,27 @@
                     mir::ProjectionElem::ConstantIndex { offset,
                                                          from_end: false,
                                                          min_length: _ } => {
-                        let lloffset = bx.cx().const_usize(offset as u64);
+                        let lloffset = bx.cx().const_usize(*offset as u64);
                         cg_base.project_index(bx, lloffset)
                     }
                     mir::ProjectionElem::ConstantIndex { offset,
                                                          from_end: true,
                                                          min_length: _ } => {
-                        let lloffset = bx.cx().const_usize(offset as u64);
+                        let lloffset = bx.cx().const_usize(*offset as u64);
                         let lllen = cg_base.len(bx.cx());
                         let llindex = bx.sub(lllen, lloffset);
                         cg_base.project_index(bx, llindex)
                     }
                     mir::ProjectionElem::Subslice { from, to } => {
                         let mut subslice = cg_base.project_index(bx,
-                            bx.cx().const_usize(from as u64));
+                            bx.cx().const_usize(*from as u64));
                         let projected_ty = PlaceTy::from_ty(cg_base.layout.ty)
-                            .projection_ty(tcx, &projection.elem).ty;
+                            .projection_ty(tcx, elem).ty;
                         subslice.layout = bx.cx().layout_of(self.monomorphize(&projected_ty));
 
                         if subslice.layout.is_unsized() {
                             subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(),
-                                bx.cx().const_usize((from as u64) + (to as u64))));
+                                bx.cx().const_usize((*from as u64) + (*to as u64))));
                         }
 
                         // Cast the place pointer type to the new
@@ -570,7 +575,7 @@
                         subslice
                     }
                     mir::ProjectionElem::Downcast(_, v) => {
-                        cg_base.project_downcast(bx, v)
+                        cg_base.project_downcast(bx, *v)
                     }
                 }
             }
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 9da1e50..f21836a 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -64,14 +64,14 @@
                         // index into the struct, and this case isn't
                         // important enough for it.
                         debug!("codegen_rvalue: creating ugly alloca");
-                        let scratch = PlaceRef::alloca(&mut bx, operand.layout, "__unsize_temp");
+                        let scratch = PlaceRef::alloca(&mut bx, operand.layout);
                         scratch.storage_live(&mut bx);
                         operand.val.store(&mut bx, scratch);
                         base::coerce_unsized_into(&mut bx, scratch, dest);
                         scratch.storage_dead(&mut bx);
                     }
                     OperandValue::Ref(llref, None, align) => {
-                        let source = PlaceRef::new_sized(llref, operand.layout, align);
+                        let source = PlaceRef::new_sized_aligned(llref, operand.layout, align);
                         base::coerce_unsized_into(&mut bx, source, dest);
                     }
                     OperandValue::Ref(_, Some(_), _) => {
@@ -522,7 +522,7 @@
         // because codegen_place() panics if Local is operand.
         if let mir::Place {
             base: mir::PlaceBase::Local(index),
-            projection: None,
+            projection: box [],
         } = *place {
             if let LocalRef::Operand(Some(op)) = self.locals[index] {
                 if let ty::Array(_, n) = op.layout.ty.sty {
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index 3617f3a..dab7dfc 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -16,12 +16,12 @@
 
         self.set_debug_loc(&mut bx, statement.source_info);
         match statement.kind {
-            mir::StatementKind::Assign(ref place, ref rvalue) => {
+            mir::StatementKind::Assign(box(ref place, ref rvalue)) => {
                 if let mir::Place {
                     base: mir::PlaceBase::Local(index),
-                    projection: None,
-                } = *place {
-                    match self.locals[index] {
+                    projection: box [],
+                } = place {
+                    match self.locals[*index] {
                         LocalRef::Place(cg_dest) => {
                             self.codegen_rvalue(bx, cg_dest, rvalue)
                         }
@@ -29,8 +29,22 @@
                             self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue)
                         }
                         LocalRef::Operand(None) => {
-                            let (bx, operand) = self.codegen_rvalue_operand(bx, rvalue);
-                            self.locals[index] = LocalRef::Operand(Some(operand));
+                            let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue);
+                            if let Some(name) = self.mir.local_decls[*index].name {
+                                match operand.val {
+                                    OperandValue::Ref(x, ..) |
+                                    OperandValue::Immediate(x) => {
+                                        bx.set_var_name(x, name);
+                                    }
+                                    OperandValue::Pair(a, b) => {
+                                        // FIXME(eddyb) these are scalar components,
+                                        // maybe extract the high-level fields?
+                                        bx.set_var_name(a, format_args!("{}.0", name));
+                                        bx.set_var_name(b, format_args!("{}.1", name));
+                                    }
+                                }
+                            }
+                            self.locals[*index] = LocalRef::Operand(Some(operand));
                             bx
                         }
                         LocalRef::Operand(Some(op)) => {
@@ -50,7 +64,7 @@
                     self.codegen_rvalue(bx, cg_dest, rvalue)
                 }
             }
-            mir::StatementKind::SetDiscriminant{ref place, variant_index} => {
+            mir::StatementKind::SetDiscriminant{box ref place, variant_index} => {
                 self.codegen_place(&mut bx, &place.as_ref())
                     .codegen_set_discr(&mut bx, variant_index);
                 bx
diff --git a/src/librustc_codegen_ssa/mono_item.rs b/src/librustc_codegen_ssa/mono_item.rs
index 4446f1a..5801963 100644
--- a/src/librustc_codegen_ssa/mono_item.rs
+++ b/src/librustc_codegen_ssa/mono_item.rs
@@ -58,7 +58,7 @@
                self.to_raw_string(),
                cx.codegen_unit().name());
 
-        let symbol_name = self.symbol_name(cx.tcx()).as_str();
+        let symbol_name = self.symbol_name(cx.tcx()).name.as_str();
 
         debug!("symbol {}", &symbol_name);
 
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index 3a144f0..1886701 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -109,13 +109,12 @@
         rhs: Self::Value,
     ) -> (Self::Value, Self::Value);
 
-    fn alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value;
-    fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value;
+    fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
+    fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
     fn array_alloca(
         &mut self,
         ty: Self::Type,
         len: Self::Value,
-        name: &str,
         align: Align,
     ) -> Self::Value;
 
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index be2fa72..9c16b86 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -57,5 +57,5 @@
         span: Span,
     );
     fn insert_reference_to_gdb_debug_scripts_section_global(&mut self);
-    fn set_value_name(&mut self, value: Self::Value, name: &str);
+    fn set_var_name(&mut self, value: Self::Value, name: impl ToString);
 }
diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs
index ede30a0..7c79cd6 100644
--- a/src/librustc_codegen_ssa/traits/intrinsic.rs
+++ b/src/librustc_codegen_ssa/traits/intrinsic.rs
@@ -1,6 +1,6 @@
 use super::BackendTypes;
 use crate::mir::operand::OperandRef;
-use rustc::ty::Ty;
+use rustc::ty::{self, Ty};
 use rustc_target::abi::call::FnType;
 use syntax_pos::Span;
 
@@ -10,7 +10,7 @@
     /// add them to librustc_codegen_llvm/context.rs
     fn codegen_intrinsic_call(
         &mut self,
-        callee_ty: Ty<'tcx>,
+        instance: ty::Instance<'tcx>,
         fn_ty: &FnType<'tcx, Ty<'tcx>>,
         args: &[OperandRef<'tcx, Self::Value>],
         llresult: Self::Value,
diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs
index 6983311..73c4c05 100644
--- a/src/librustc_codegen_ssa/traits/statics.rs
+++ b/src/librustc_codegen_ssa/traits/statics.rs
@@ -1,5 +1,5 @@
 use super::BackendTypes;
-use syntax_pos::symbol::LocalInternedString;
+use syntax_pos::symbol::Symbol;
 use rustc::hir::def_id::DefId;
 use rustc::ty::layout::Align;
 
@@ -12,8 +12,8 @@
     fn get_static(&mut self, def_id: DefId) -> Self::Value;
     fn static_panic_msg(
         &mut self,
-        msg: Option<LocalInternedString>,
-        filename: LocalInternedString,
+        msg: Option<Symbol>,
+        filename: Symbol,
         line: Self::Value,
         col: Self::Value,
         kind: &str,
diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs
index 4ea375b..1201446 100644
--- a/src/librustc_codegen_utils/lib.rs
+++ b/src/librustc_codegen_utils/lib.rs
@@ -10,7 +10,6 @@
 #![feature(core_intrinsics)]
 #![feature(never_type)]
 #![feature(nll)]
-#![feature(rustc_diagnostic_macros)]
 #![feature(in_band_lifetimes)]
 
 #![recursion_limit="256"]
diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs
index f562744..51269be 100644
--- a/src/librustc_codegen_utils/symbol_names_test.rs
+++ b/src/librustc_codegen_utils/symbol_names_test.rs
@@ -40,7 +40,7 @@
                 let instance = Instance::mono(tcx, def_id);
                 let mangled = self.tcx.symbol_name(instance);
                 tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled));
-                if let Ok(demangling) = rustc_demangle::try_demangle(&mangled.as_str()) {
+                if let Ok(demangling) = rustc_demangle::try_demangle(&mangled.name.as_str()) {
                     tcx.sess.span_err(attr.span, &format!("demangling({})", demangling));
                     tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling));
                 }
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 288676c..be9f79c 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -26,5 +26,5 @@
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
 
 [dependencies.parking_lot]
-version = "0.7"
+version = "0.9"
 features = ["nightly"]
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index 6f40d05..6e80b48 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -149,7 +149,7 @@
 
             #[inline]
             $v const unsafe fn from_u32_unchecked(value: u32) -> Self {
-                unsafe { $type { private: value } }
+                $type { private: value }
             }
 
             /// Extracts the value of this index as an integer.
diff --git a/src/librustc_data_structures/obligation_forest/graphviz.rs b/src/librustc_data_structures/obligation_forest/graphviz.rs
index a0363e1..b2120b1 100644
--- a/src/librustc_data_structures/obligation_forest/graphviz.rs
+++ b/src/librustc_data_structures/obligation_forest/graphviz.rs
@@ -74,9 +74,9 @@
             .flat_map(|i| {
                 let node = &self.nodes[i];
 
-                node.parent.iter().map(|p| p.get())
-                    .chain(node.dependents.iter().map(|p| p.get()))
-                    .map(move |p| (p, i))
+                node.parent.iter()
+                    .chain(node.dependents.iter())
+                    .map(move |p| (p.index(), i))
             })
             .collect()
     }
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 04d2b23..189506b 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -9,7 +9,7 @@
 //! `ObligationForest` supports two main public operations (there are a
 //! few others not discussed here):
 //!
-//! 1. Add a new root obligations (`push_tree`).
+//! 1. Add a new root obligations (`register_obligation`).
 //! 2. Process the pending obligations (`process_obligations`).
 //!
 //! When a new obligation `N` is added, it becomes the root of an
@@ -20,13 +20,13 @@
 //! with every pending obligation (so that will include `N`, the first
 //! time). The callback also receives a (mutable) reference to the
 //! per-tree state `T`. The callback should process the obligation `O`
-//! that it is given and return one of three results:
+//! that it is given and return a `ProcessResult`:
 //!
-//! - `Ok(None)` -> ambiguous result. Obligation was neither a success
+//! - `Unchanged` -> ambiguous result. Obligation was neither a success
 //!   nor a failure. It is assumed that further attempts to process the
 //!   obligation will yield the same result unless something in the
 //!   surrounding environment changes.
-//! - `Ok(Some(C))` - the obligation was *shallowly successful*. The
+//! - `Changed(C)` - the obligation was *shallowly successful*. The
 //!   vector `C` is a list of subobligations. The meaning of this is that
 //!   `O` was successful on the assumption that all the obligations in `C`
 //!   are also successful. Therefore, `O` is only considered a "true"
@@ -34,7 +34,7 @@
 //!   state and the obligations in `C` become the new pending
 //!   obligations. They will be processed the next time you call
 //!   `process_obligations`.
-//! - `Err(E)` -> obligation failed with error `E`. We will collect this
+//! - `Error(E)` -> obligation failed with error `E`. We will collect this
 //!   error and return it from `process_obligations`, along with the
 //!   "backtrace" of obligations (that is, the list of obligations up to
 //!   and including the root of the failed obligation). No further
@@ -47,55 +47,50 @@
 //! - `completed`: a list of obligations where processing was fully
 //!   completed without error (meaning that all transitive subobligations
 //!   have also been completed). So, for example, if the callback from
-//!   `process_obligations` returns `Ok(Some(C))` for some obligation `O`,
+//!   `process_obligations` returns `Changed(C)` for some obligation `O`,
 //!   then `O` will be considered completed right away if `C` is the
 //!   empty vector. Otherwise it will only be considered completed once
 //!   all the obligations in `C` have been found completed.
 //! - `errors`: a list of errors that occurred and associated backtraces
 //!   at the time of error, which can be used to give context to the user.
 //! - `stalled`: if true, then none of the existing obligations were
-//!   *shallowly successful* (that is, no callback returned `Ok(Some(_))`).
+//!   *shallowly successful* (that is, no callback returned `Changed(_)`).
 //!   This implies that all obligations were either errors or returned an
 //!   ambiguous result, which means that any further calls to
 //!   `process_obligations` would simply yield back further ambiguous
 //!   results. This is used by the `FulfillmentContext` to decide when it
 //!   has reached a steady state.
 //!
-//! #### Snapshots
-//!
-//! The `ObligationForest` supports a limited form of snapshots; see
-//! `start_snapshot`, `commit_snapshot`, and `rollback_snapshot`. In
-//! particular, you can use a snapshot to roll back new root
-//! obligations. However, it is an error to attempt to
-//! `process_obligations` during a snapshot.
-//!
 //! ### Implementation details
 //!
 //! For the most part, comments specific to the implementation are in the
 //! code. This file only contains a very high-level overview. Basically,
 //! the forest is stored in a vector. Each element of the vector is a node
-//! in some tree. Each node in the vector has the index of an (optional)
-//! parent and (for convenience) its root (which may be itself). It also
-//! has a current state, described by `NodeState`. After each
-//! processing step, we compress the vector to remove completed and error
-//! nodes, which aren't needed anymore.
+//! in some tree. Each node in the vector has the index of its dependents,
+//! including the first dependent which is known as the parent. It also
+//! has a current state, described by `NodeState`. After each processing
+//! step, we compress the vector to remove completed and error nodes, which
+//! aren't needed anymore.
 
 use crate::fx::{FxHashMap, FxHashSet};
+use crate::indexed_vec::Idx;
+use crate::newtype_index;
 
-use std::cell::Cell;
+use std::cell::{Cell, RefCell};
 use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash;
 use std::marker::PhantomData;
 
-mod node_index;
-use self::node_index::NodeIndex;
-
 mod graphviz;
 
 #[cfg(test)]
 mod tests;
 
+newtype_index! {
+    pub struct NodeIndex { .. }
+}
+
 pub trait ForestObligation : Clone + Debug {
     type Predicate : Clone + hash::Hash + Eq + Debug;
 
@@ -148,18 +143,22 @@
     /// At the end of processing, those nodes will be removed by a
     /// call to `compress`.
     ///
-    /// At all times we maintain the invariant that every node appears
-    /// at a higher index than its parent. This is needed by the
-    /// backtrace iterator (which uses `split_at`).
+    /// Ideally, this would be an `IndexVec<NodeIndex, Node<O>>`. But that is
+    /// slower, because this vector is accessed so often that the
+    /// `u32`-to-`usize` conversions required for accesses are significant.
     nodes: Vec<Node<O>>,
 
     /// A cache of predicates that have been successfully completed.
     done_cache: FxHashSet<O::Predicate>,
 
-    /// An cache of the nodes in `nodes`, indexed by predicate.
+    /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
+    /// its contents are not guaranteed to match those of `nodes`. See the
+    /// comments in `process_obligation` for details.
     waiting_cache: FxHashMap<O::Predicate, NodeIndex>,
 
-    scratch: Option<Vec<usize>>,
+    /// A scratch vector reused in various operations, to avoid allocating new
+    /// vectors.
+    scratch: RefCell<Vec<usize>>,
 
     obligation_tree_id_generator: ObligationTreeIdGenerator,
 
@@ -178,19 +177,41 @@
     obligation: O,
     state: Cell<NodeState>,
 
-    /// The parent of a node - the original obligation of
-    /// which it is a subobligation. Except for error reporting,
-    /// it is just like any member of `dependents`.
+    /// The parent of a node - the original obligation of which it is a
+    /// subobligation. Except for error reporting, it is just like any member
+    /// of `dependents`.
+    ///
+    /// Unlike `ObligationForest::nodes`, this uses `NodeIndex` rather than
+    /// `usize` for the index, because keeping the size down is more important
+    /// than the cost of converting to a `usize` for indexing.
     parent: Option<NodeIndex>,
 
-    /// Obligations that depend on this obligation for their
-    /// completion. They must all be in a non-pending state.
+    /// Obligations that depend on this obligation for their completion. They
+    /// must all be in a non-pending state.
+    ///
+    /// This uses `NodeIndex` for the same reason as `parent`.
     dependents: Vec<NodeIndex>,
 
     /// Identifier of the obligation tree to which this node belongs.
     obligation_tree_id: ObligationTreeId,
 }
 
+impl<O> Node<O> {
+    fn new(
+        parent: Option<NodeIndex>,
+        obligation: O,
+        obligation_tree_id: ObligationTreeId
+    ) -> Node<O> {
+        Node {
+            obligation,
+            state: Cell::new(NodeState::Pending),
+            parent,
+            dependents: vec![],
+            obligation_tree_id,
+        }
+    }
+}
+
 /// The state of one node in some tree within the forest. This
 /// represents the current state of processing for the obligation (of
 /// type `O`) associated with this node.
@@ -262,7 +283,7 @@
             nodes: vec![],
             done_cache: Default::default(),
             waiting_cache: Default::default(),
-            scratch: Some(vec![]),
+            scratch: RefCell::new(vec![]),
             obligation_tree_id_generator: (0..).map(ObligationTreeId),
             error_cache: Default::default(),
         }
@@ -275,14 +296,12 @@
     }
 
     /// Registers an obligation.
-    ///
-    /// This CAN be done in a snapshot
     pub fn register_obligation(&mut self, obligation: O) {
         // Ignore errors here - there is no guarantee of success.
         let _ = self.register_obligation_at(obligation, None);
     }
 
-    // returns Err(()) if we already know this obligation failed.
+    // Returns Err(()) if we already know this obligation failed.
     fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>)
                               -> Result<(), ()>
     {
@@ -294,15 +313,16 @@
             Entry::Occupied(o) => {
                 debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!",
                        obligation, parent, o.get());
-                let node = &mut self.nodes[o.get().get()];
-                if let Some(parent) = parent {
+                let node = &mut self.nodes[o.get().index()];
+                if let Some(parent_index) = parent {
                     // If the node is already in `waiting_cache`, it's already
                     // been marked with a parent. (It's possible that parent
                     // has been cleared by `apply_rewrites`, though.) So just
                     // dump `parent` into `node.dependents`... unless it's
                     // already in `node.dependents` or `node.parent`.
-                    if !node.dependents.contains(&parent) && Some(parent) != node.parent {
-                        node.dependents.push(parent);
+                    if !node.dependents.contains(&parent_index) &&
+                       Some(parent_index) != node.parent {
+                        node.dependents.push(parent_index);
                     }
                 }
                 if let NodeState::Error = node.state.get() {
@@ -316,9 +336,8 @@
                        obligation, parent, self.nodes.len());
 
                 let obligation_tree_id = match parent {
-                    Some(p) => {
-                        let parent_node = &self.nodes[p.get()];
-                        parent_node.obligation_tree_id
+                    Some(parent_index) => {
+                        self.nodes[parent_index.index()].obligation_tree_id
                     }
                     None => self.obligation_tree_id_generator.next().unwrap()
                 };
@@ -342,13 +361,11 @@
     }
 
     /// Converts all remaining obligations to the given error.
-    ///
-    /// This cannot be done during a snapshot.
     pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> {
         let mut errors = vec![];
-        for index in 0..self.nodes.len() {
-            if let NodeState::Pending = self.nodes[index].state.get() {
-                let backtrace = self.error_at(index);
+        for (i, node) in self.nodes.iter().enumerate() {
+            if let NodeState::Pending = node.state.get() {
+                let backtrace = self.error_at(i);
                 errors.push(Error {
                     error: error.clone(),
                     backtrace,
@@ -373,7 +390,6 @@
 
     fn insert_into_error_cache(&mut self, node_index: usize) {
         let node = &self.nodes[node_index];
-
         self.error_cache
             .entry(node.obligation_tree_id)
             .or_default()
@@ -393,16 +409,22 @@
         let mut errors = vec![];
         let mut stalled = true;
 
-        for index in 0..self.nodes.len() {
-            debug!("process_obligations: node {} == {:?}", index, self.nodes[index]);
+        for i in 0..self.nodes.len() {
+            let node = &mut self.nodes[i];
 
-            let result = match self.nodes[index] {
-                Node { ref state, ref mut obligation, .. } if state.get() == NodeState::Pending =>
-                    processor.process_obligation(obligation),
+            debug!("process_obligations: node {} == {:?}", i, node);
+
+            // `processor.process_obligation` can modify the predicate within
+            // `node.obligation`, and that predicate is the key used for
+            // `self.waiting_cache`. This means that `self.waiting_cache` can
+            // get out of sync with `nodes`. It's not very common, but it does
+            // happen, and code in `compress` has to allow for it.
+            let result = match node.state.get() {
+                NodeState::Pending => processor.process_obligation(&mut node.obligation),
                 _ => continue
             };
 
-            debug!("process_obligations: node {} got result {:?}", index, result);
+            debug!("process_obligations: node {} got result {:?}", i, result);
 
             match result {
                 ProcessResult::Unchanged => {
@@ -411,23 +433,23 @@
                 ProcessResult::Changed(children) => {
                     // We are not (yet) stalled.
                     stalled = false;
-                    self.nodes[index].state.set(NodeState::Success);
+                    node.state.set(NodeState::Success);
 
                     for child in children {
                         let st = self.register_obligation_at(
                             child,
-                            Some(NodeIndex::new(index))
+                            Some(NodeIndex::new(i))
                         );
                         if let Err(()) = st {
-                            // error already reported - propagate it
+                            // Error already reported - propagate it
                             // to our node.
-                            self.error_at(index);
+                            self.error_at(i);
                         }
                     }
                 }
                 ProcessResult::Error(err) => {
                     stalled = false;
-                    let backtrace = self.error_at(index);
+                    let backtrace = self.error_at(i);
                     errors.push(Error {
                         error: err,
                         backtrace,
@@ -448,8 +470,6 @@
 
         self.mark_as_waiting();
         self.process_cycles(processor);
-
-        // Now we have to compress the result
         let completed = self.compress(do_completed);
 
         debug!("process_obligations: complete");
@@ -465,107 +485,109 @@
     /// 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>(&mut self, processor: &mut P)
+    fn process_cycles<P>(&self, processor: &mut P)
         where P: ObligationProcessor<Obligation=O>
     {
-        let mut stack = self.scratch.take().unwrap();
+        let mut stack = self.scratch.replace(vec![]);
         debug_assert!(stack.is_empty());
 
         debug!("process_cycles()");
 
-        for index in 0..self.nodes.len() {
+        for (i, node) in self.nodes.iter().enumerate() {
             // For rustc-benchmarks/inflate-0.1.0 this state test is extremely
             // hot and the state is almost always `Pending` or `Waiting`. It's
             // a win to handle the no-op cases immediately to avoid the cost of
             // the function call.
-            let state = self.nodes[index].state.get();
-            match state {
+            match node.state.get() {
                 NodeState::Waiting | NodeState::Pending | NodeState::Done | NodeState::Error => {},
-                _ => self.find_cycles_from_node(&mut stack, processor, index),
+                _ => self.find_cycles_from_node(&mut stack, processor, i),
             }
         }
 
         debug!("process_cycles: complete");
 
         debug_assert!(stack.is_empty());
-        self.scratch = Some(stack);
+        self.scratch.replace(stack);
     }
 
-    fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>,
-                                processor: &mut P, index: usize)
+    fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>, processor: &mut P, i: usize)
         where P: ObligationProcessor<Obligation=O>
     {
-        let node = &self.nodes[index];
-        let state = node.state.get();
-        match state {
+        let node = &self.nodes[i];
+        match node.state.get() {
             NodeState::OnDfsStack => {
-                let index =
-                    stack.iter().rposition(|n| *n == index).unwrap();
-                processor.process_backedge(stack[index..].iter().map(GetObligation(&self.nodes)),
+                let i = stack.iter().rposition(|n| *n == i).unwrap();
+                processor.process_backedge(stack[i..].iter().map(GetObligation(&self.nodes)),
                                            PhantomData);
             }
             NodeState::Success => {
                 node.state.set(NodeState::OnDfsStack);
-                stack.push(index);
-                for dependent in node.parent.iter().chain(node.dependents.iter()) {
-                    self.find_cycles_from_node(stack, processor, dependent.get());
+                stack.push(i);
+                for index in node.parent.iter().chain(node.dependents.iter()) {
+                    self.find_cycles_from_node(stack, processor, index.index());
                 }
                 stack.pop();
                 node.state.set(NodeState::Done);
             },
             NodeState::Waiting | NodeState::Pending => {
-                // this node is still reachable from some pending node. We
+                // This node is still reachable from some pending node. We
                 // will get to it when they are all processed.
             }
             NodeState::Done | NodeState::Error => {
-                // already processed that node
+                // Already processed that node.
             }
         };
     }
 
     /// Returns a vector of obligations for `p` and all of its
     /// ancestors, putting them into the error state in the process.
-    fn error_at(&mut self, p: usize) -> Vec<O> {
-        let mut error_stack = self.scratch.take().unwrap();
+    fn error_at(&self, mut i: usize) -> Vec<O> {
+        let mut error_stack = self.scratch.replace(vec![]);
         let mut trace = vec![];
 
-        let mut n = p;
         loop {
-            self.nodes[n].state.set(NodeState::Error);
-            trace.push(self.nodes[n].obligation.clone());
-            error_stack.extend(self.nodes[n].dependents.iter().map(|x| x.get()));
+            let node = &self.nodes[i];
+            node.state.set(NodeState::Error);
+            trace.push(node.obligation.clone());
+            error_stack.extend(node.dependents.iter().map(|index| index.index()));
 
-            // loop to the parent
-            match self.nodes[n].parent {
-                Some(q) => n = q.get(),
+            // Loop to the parent.
+            match node.parent {
+                Some(parent_index) => i = parent_index.index(),
                 None => break
             }
         }
 
         while let Some(i) = error_stack.pop() {
-            match self.nodes[i].state.get() {
+            let node = &self.nodes[i];
+            match node.state.get() {
                 NodeState::Error => continue,
-                _ => self.nodes[i].state.set(NodeState::Error),
+                _ => node.state.set(NodeState::Error),
             }
 
-            let node = &self.nodes[i];
-
             error_stack.extend(
-                node.parent.iter().chain(node.dependents.iter()).map(|x| x.get())
+                node.parent.iter().chain(node.dependents.iter()).map(|index| index.index())
             );
         }
 
-        self.scratch = Some(error_stack);
+        self.scratch.replace(error_stack);
         trace
     }
 
-    #[inline]
-    fn mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
+    // This always-inlined function is for the hot call site.
+    #[inline(always)]
+    fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
         for dependent in node.parent.iter().chain(node.dependents.iter()) {
-            self.mark_as_waiting_from(&self.nodes[dependent.get()]);
+            self.mark_as_waiting_from(&self.nodes[dependent.index()]);
         }
     }
 
+    // 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)
+    }
+
     /// Marks all nodes that depend on a pending node as `NodeState::Waiting`.
     fn mark_as_waiting(&self) {
         for node in &self.nodes {
@@ -576,7 +598,8 @@
 
         for node in &self.nodes {
             if node.state.get() == NodeState::Pending {
-                self.mark_neighbors_as_waiting_from(node);
+                // This call site is hot.
+                self.inlined_mark_neighbors_as_waiting_from(node);
             }
         }
     }
@@ -588,7 +611,8 @@
             NodeState::Pending | NodeState::Done => {},
         }
 
-        self.mark_neighbors_as_waiting_from(node);
+        // This call site is cold.
+        self.uninlined_mark_neighbors_as_waiting_from(node);
     }
 
     /// Compresses the vector, removing all popped nodes. This adjusts
@@ -600,7 +624,7 @@
     #[inline(never)]
     fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
         let nodes_len = self.nodes.len();
-        let mut node_rewrites: Vec<_> = self.scratch.take().unwrap();
+        let mut node_rewrites: Vec<_> = self.scratch.replace(vec![]);
         node_rewrites.extend(0..nodes_len);
         let mut dead_nodes = 0;
 
@@ -611,7 +635,8 @@
         //     self.nodes[i - dead_nodes..i] are all dead
         //     self.nodes[i..] are unchanged
         for i in 0..self.nodes.len() {
-            match self.nodes[i].state.get() {
+            let node = &self.nodes[i];
+            match node.state.get() {
                 NodeState::Pending | NodeState::Waiting => {
                     if dead_nodes > 0 {
                         self.nodes.swap(i, i - dead_nodes);
@@ -619,13 +644,16 @@
                     }
                 }
                 NodeState::Done => {
-                    // Avoid cloning the key (predicate) in case it exists in the waiting cache
+                    // This lookup can fail because the contents of
+                    // `self.waiting_cache` is not guaranteed to match those of
+                    // `self.nodes`. See the comment in `process_obligation`
+                    // for more details.
                     if let Some((predicate, _)) = self.waiting_cache
-                        .remove_entry(self.nodes[i].obligation.as_predicate())
+                        .remove_entry(node.obligation.as_predicate())
                     {
                         self.done_cache.insert(predicate);
                     } else {
-                        self.done_cache.insert(self.nodes[i].obligation.as_predicate().clone());
+                        self.done_cache.insert(node.obligation.as_predicate().clone());
                     }
                     node_rewrites[i] = nodes_len;
                     dead_nodes += 1;
@@ -634,7 +662,7 @@
                     // We *intentionally* remove the node from the cache at this point. Otherwise
                     // tests must come up with a different type on every type error they
                     // check against.
-                    self.waiting_cache.remove(self.nodes[i].obligation.as_predicate());
+                    self.waiting_cache.remove(node.obligation.as_predicate());
                     node_rewrites[i] = nodes_len;
                     dead_nodes += 1;
                     self.insert_into_error_cache(i);
@@ -646,12 +674,11 @@
         // No compression needed.
         if dead_nodes == 0 {
             node_rewrites.truncate(0);
-            self.scratch = Some(node_rewrites);
+            self.scratch.replace(node_rewrites);
             return if do_completed == DoCompleted::Yes { Some(vec![]) } else { None };
         }
 
-        // Pop off all the nodes we killed and extract the success
-        // stories.
+        // Pop off all the nodes we killed and extract the success stories.
         let successful = if do_completed == DoCompleted::Yes {
             Some((0..dead_nodes)
                 .map(|_| self.nodes.pop().unwrap())
@@ -670,7 +697,7 @@
         self.apply_rewrites(&node_rewrites);
 
         node_rewrites.truncate(0);
-        self.scratch = Some(node_rewrites);
+        self.scratch.replace(node_rewrites);
 
         successful
     }
@@ -680,58 +707,41 @@
 
         for node in &mut self.nodes {
             if let Some(index) = node.parent {
-                let new_index = node_rewrites[index.get()];
-                if new_index >= nodes_len {
-                    // parent dead due to error
+                let new_i = node_rewrites[index.index()];
+                if new_i >= nodes_len {
                     node.parent = None;
                 } else {
-                    node.parent = Some(NodeIndex::new(new_index));
+                    node.parent = Some(NodeIndex::new(new_i));
                 }
             }
 
             let mut i = 0;
             while i < node.dependents.len() {
-                let new_index = node_rewrites[node.dependents[i].get()];
-                if new_index >= nodes_len {
+                let new_i = node_rewrites[node.dependents[i].index()];
+                if new_i >= nodes_len {
                     node.dependents.swap_remove(i);
                 } else {
-                    node.dependents[i] = NodeIndex::new(new_index);
+                    node.dependents[i] = NodeIndex::new(new_i);
                     i += 1;
                 }
             }
         }
 
-        let mut kill_list = vec![];
-        for (predicate, index) in &mut self.waiting_cache {
-            let new_index = node_rewrites[index.get()];
-            if new_index >= nodes_len {
-                kill_list.push(predicate.clone());
+        // This updating of `self.waiting_cache` is necessary because the
+        // removal of nodes within `compress` can fail. See above.
+        self.waiting_cache.retain(|_predicate, index| {
+            let new_i = node_rewrites[index.index()];
+            if new_i >= nodes_len {
+                false
             } else {
-                *index = NodeIndex::new(new_index);
+                *index = NodeIndex::new(new_i);
+                true
             }
-        }
-
-        for predicate in kill_list { self.waiting_cache.remove(&predicate); }
+        });
     }
 }
 
-impl<O> Node<O> {
-    fn new(
-        parent: Option<NodeIndex>,
-        obligation: O,
-        obligation_tree_id: ObligationTreeId
-    ) -> Node<O> {
-        Node {
-            obligation,
-            state: Cell::new(NodeState::Pending),
-            parent,
-            dependents: vec![],
-            obligation_tree_id,
-        }
-    }
-}
-
-// I need a Clone closure
+// I need a Clone closure.
 #[derive(Clone)]
 struct GetObligation<'a, O>(&'a [Node<O>]);
 
diff --git a/src/librustc_data_structures/obligation_forest/node_index.rs b/src/librustc_data_structures/obligation_forest/node_index.rs
deleted file mode 100644
index 69ea473..0000000
--- a/src/librustc_data_structures/obligation_forest/node_index.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use std::num::NonZeroU32;
-use std::u32;
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct NodeIndex {
-    index: NonZeroU32,
-}
-
-impl NodeIndex {
-    #[inline]
-    pub fn new(value: usize) -> NodeIndex {
-        assert!(value < (u32::MAX as usize));
-        NodeIndex { index: NonZeroU32::new((value as u32) + 1).unwrap() }
-    }
-
-    #[inline]
-    pub fn get(self) -> usize {
-        (self.index.get() - 1) as usize
-    }
-}
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index b030517..25f67b3 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -11,8 +11,9 @@
 
 [dependencies]
 graphviz = { path = "../libgraphviz" }
+lazy_static = "1.0"
 log = "0.4"
-env_logger = { version = "0.5", default-features = false }
+env_logger = { version = "0.6", default-features = false }
 rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
 rustc_ast_borrowck = { path = "../librustc_ast_borrowck" }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 9a6a12e..8c5d853 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -9,7 +9,6 @@
 #![feature(box_syntax)]
 #![cfg_attr(unix, feature(libc))]
 #![feature(nll)]
-#![feature(rustc_diagnostic_macros)]
 #![feature(set_stdio)]
 #![feature(no_debug)]
 #![feature(integer_atomics)]
@@ -21,6 +20,8 @@
 extern crate libc;
 #[macro_use]
 extern crate log;
+#[macro_use]
+extern crate lazy_static;
 
 pub extern crate rustc_plugin_impl as plugin;
 
@@ -36,8 +37,8 @@
 use rustc::lint::Lint;
 use rustc::lint;
 use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::util::common::{ErrorReported, install_panic_hook, print_time_passes_entry};
-use rustc::util::common::{set_time_depth, time};
+use rustc::ty::TyCtxt;
+use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported};
 use rustc_metadata::locator;
 use rustc_metadata::cstore::CStore;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
@@ -133,8 +134,11 @@
 
 impl Callbacks for TimePassesCallbacks {
     fn config(&mut self, config: &mut interface::Config) {
+        // If a --prints=... option has been given, we don't print the "total"
+        // time because it will mess up the --prints output. See #64339.
         self.time_passes =
-            config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time;
+            config.opts.prints.is_empty() &&
+            (config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time);
     }
 }
 
@@ -162,8 +166,6 @@
         None => return Ok(()),
     };
 
-    install_panic_hook();
-
     let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
 
     let mut dummy_config = |sopts, cfg, diagnostic_output| {
@@ -1152,63 +1154,107 @@
     }
 }
 
-/// Runs a procedure which will detect panics in the compiler and print nicer
-/// error messages rather than just failing the test.
+/// Runs a closure and catches unwinds triggered by fatal errors.
 ///
-/// The diagnostic emitter yielded to the procedure should be used for reporting
-/// errors of the compiler.
-pub fn report_ices_to_stderr_if_any<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported> {
+/// The compiler currently unwinds with a special sentinel value to abort
+/// compilation on fatal errors. This function catches that sentinel and turns
+/// the panic into a `Result` instead.
+pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported> {
     catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
         if value.is::<errors::FatalErrorMarker>() {
             ErrorReported
         } else {
-            // Thread panicked without emitting a fatal diagnostic
-            eprintln!("");
-
-            let emitter = Box::new(errors::emitter::EmitterWriter::stderr(
-                errors::ColorConfig::Auto,
-                None,
-                false,
-                false,
-                None,
-            ));
-            let handler = errors::Handler::with_emitter(true, None, emitter);
-
-            // a .span_bug or .bug call has already printed what
-            // it wants to print.
-            if !value.is::<errors::ExplicitBug>() {
-                handler.emit(&MultiSpan::new(),
-                             "unexpected panic",
-                             errors::Level::Bug);
-            }
-
-            let mut xs: Vec<Cow<'static, str>> = vec![
-                "the compiler unexpectedly panicked. this is a bug.".into(),
-                format!("we would appreciate a bug report: {}", BUG_REPORT_URL).into(),
-                format!("rustc {} running on {}",
-                        option_env!("CFG_VERSION").unwrap_or("unknown_version"),
-                        config::host_triple()).into(),
-            ];
-
-            if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
-                xs.push(format!("compiler flags: {}", flags.join(" ")).into());
-
-                if excluded_cargo_defaults {
-                    xs.push("some of the compiler flags provided by cargo are hidden".into());
-                }
-            }
-
-            for note in &xs {
-                handler.emit(&MultiSpan::new(),
-                             note,
-                             errors::Level::Note);
-            }
-
-            panic::resume_unwind(Box::new(errors::FatalErrorMarker));
+            panic::resume_unwind(value);
         }
     })
 }
 
+lazy_static! {
+    static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static> = {
+        let hook = panic::take_hook();
+        panic::set_hook(Box::new(|info| report_ice(info, BUG_REPORT_URL)));
+        hook
+    };
+}
+
+/// Prints the ICE message, including backtrace and query stack.
+///
+/// The message will point the user at `bug_report_url` to report the ICE.
+///
+/// When `install_ice_hook` is called, this function will be called as the panic
+/// hook.
+pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
+    // Invoke the default handler, which prints the actual panic message and optionally a backtrace
+    (*DEFAULT_HOOK)(info);
+
+    // Separate the output with an empty line
+    eprintln!();
+
+    let emitter = Box::new(errors::emitter::EmitterWriter::stderr(
+        errors::ColorConfig::Auto,
+        None,
+        false,
+        false,
+        None,
+    ));
+    let handler = errors::Handler::with_emitter(true, None, emitter);
+
+    // a .span_bug or .bug call has already printed what
+    // it wants to print.
+    if !info.payload().is::<errors::ExplicitBug>() {
+        handler.emit(&MultiSpan::new(),
+                     "unexpected panic",
+                     errors::Level::Bug);
+    }
+
+    let mut xs: Vec<Cow<'static, str>> = vec![
+        "the compiler unexpectedly panicked. this is a bug.".into(),
+        format!("we would appreciate a bug report: {}", bug_report_url).into(),
+        format!("rustc {} running on {}",
+                option_env!("CFG_VERSION").unwrap_or("unknown_version"),
+                config::host_triple()).into(),
+    ];
+
+    if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
+        xs.push(format!("compiler flags: {}", flags.join(" ")).into());
+
+        if excluded_cargo_defaults {
+            xs.push("some of the compiler flags provided by cargo are hidden".into());
+        }
+    }
+
+    for note in &xs {
+        handler.emit(&MultiSpan::new(),
+                     note,
+                     errors::Level::Note);
+    }
+
+    // If backtraces are enabled, also print the query stack
+    let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
+
+    if backtrace {
+        TyCtxt::try_print_query_stack();
+    }
+
+    #[cfg(windows)]
+    unsafe {
+        if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
+            extern "system" {
+                fn DebugBreak();
+            }
+            // Trigger a debugger if we crashed during bootstrap
+            DebugBreak();
+        }
+    }
+}
+
+/// Installs a panic hook that will print the ICE message on unexpected panics.
+///
+/// A custom rustc driver can skip calling this to set up a custom ICE hook.
+pub fn install_ice_hook() {
+    lazy_static::initialize(&DEFAULT_HOOK);
+}
+
 /// This allows tools to enable rust logging without having to magically match rustc's
 /// log crate version
 pub fn init_rustc_env_logger() {
@@ -1219,7 +1265,8 @@
     let start = Instant::now();
     init_rustc_env_logger();
     let mut callbacks = TimePassesCallbacks::default();
-    let result = report_ices_to_stderr_if_any(|| {
+    install_ice_hook();
+    let result = catch_fatal_errors(|| {
         let args = env::args_os().enumerate()
             .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
                     early_error(ErrorOutputType::default(),
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index cb17401..fa9504e 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -1,7 +1,5 @@
 //! The various pretty-printing routines.
 
-use rustc::cfg;
-use rustc::cfg::graphviz::LabelledCFG;
 use rustc::hir;
 use rustc::hir::map as hir_map;
 use rustc::hir::map::blocks;
@@ -14,6 +12,7 @@
 use rustc_interface::util::ReplaceBodyWithLoop;
 use rustc_ast_borrowck as borrowck;
 use rustc_ast_borrowck::graphviz as borrowck_dot;
+use rustc_ast_borrowck::cfg::{self, graphviz::LabelledCFG};
 use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};
 
 use syntax::ast;
@@ -327,6 +326,7 @@
     }
     fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
         match node {
+            pprust::AnnNode::Crate(_) |
             pprust::AnnNode::Ident(_) |
             pprust::AnnNode::Name(_) => {},
 
@@ -432,14 +432,18 @@
         match node {
             pprust::AnnNode::Ident(&ast::Ident { name, span }) => {
                 s.s.space();
-                // FIXME #16420: this doesn't display the connections
-                // between syntax contexts
                 s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
             }
             pprust::AnnNode::Name(&name) => {
                 s.s.space();
                 s.synth_comment(name.as_u32().to_string())
             }
+            pprust::AnnNode::Crate(_) => {
+                s.s.hardbreak();
+                let verbose = self.sess.verbose();
+                s.synth_comment(syntax_pos::hygiene::debug_hygiene_data(verbose));
+                s.s.hardbreak_if_not_bol();
+            }
             _ => {}
         }
     }
diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs
index 255af31..c626dd0 100644
--- a/src/librustc_errors/annotate_snippet_emitter_writer.rs
+++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs
@@ -30,12 +30,14 @@
 impl Emitter for AnnotateSnippetEmitterWriter {
     /// The entry point for the diagnostics generation
     fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) {
-        let primary_span = db.span.clone();
-        let children = db.children.clone();
-        // FIXME(#59346): Collect suggestions (see emitter.rs)
-        let suggestions: &[_] = &[];
+        let mut children = db.children.clone();
+        let (mut primary_span, suggestions) = self.primary_span_formatted(&db);
 
-        // FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs
+        self.fix_multispans_in_std_macros(&self.source_map,
+                                          &mut primary_span,
+                                          &mut children,
+                                          &db.level,
+                                          db.handler().flags.external_macro_backtrace);
 
         self.emit_messages_default(&db.level,
                                    db.message(),
@@ -107,7 +109,7 @@
         annotated_files: Vec<FileWithAnnotatedLines>,
         primary_lo: Loc
     ) -> Vec<Slice> {
-        // FIXME(#59346): Provide a test case where `annotated_files` is > 1
+        // FIXME(#64205): Provide a test case where `annotated_files` is > 1
         annotated_files.iter().flat_map(|annotated_file| {
             annotated_file.lines.iter().map(|line| {
                 let line_source = Self::source_string(annotated_file.file.clone(), &line);
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 41d0638..7b8902f 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -18,8 +18,17 @@
 /// extending `HandlerFlags`, accessed via `self.handler.flags`.
 #[must_use]
 #[derive(Clone)]
-pub struct DiagnosticBuilder<'a> {
-    pub handler: &'a Handler,
+pub struct DiagnosticBuilder<'a>(Box<DiagnosticBuilderInner<'a>>);
+
+/// This is a large type, and often used as a return value, especially within
+/// the frequently-used `PResult` type. In theory, return value optimization
+/// (RVO) should avoid unnecessary copying. In practice, it does not (at the
+/// time of writing). The split between `DiagnosticBuilder` and
+/// `DiagnosticBuilderInner` exists to avoid many `memcpy` calls.
+#[must_use]
+#[derive(Clone)]
+struct DiagnosticBuilderInner<'a> {
+    handler: &'a Handler,
     diagnostic: Diagnostic,
     allow_suggestions: bool,
 }
@@ -52,7 +61,7 @@
     ) => {
         $(#[$attrs])*
         pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
-            self.diagnostic.$n($($name),*);
+            self.0.diagnostic.$n($($name),*);
             self
         }
     };
@@ -69,7 +78,7 @@
     ) => {
         $(#[$attrs])*
         pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
-            self.diagnostic.$n($($name),*);
+            self.0.diagnostic.$n($($name),*);
             self
         }
     };
@@ -79,24 +88,28 @@
     type Target = Diagnostic;
 
     fn deref(&self) -> &Diagnostic {
-        &self.diagnostic
+        &self.0.diagnostic
     }
 }
 
 impl<'a> DerefMut for DiagnosticBuilder<'a> {
     fn deref_mut(&mut self) -> &mut Diagnostic {
-        &mut self.diagnostic
+        &mut self.0.diagnostic
     }
 }
 
 impl<'a> DiagnosticBuilder<'a> {
+    pub fn handler(&self) -> &'a Handler{
+        self.0.handler
+    }
+
     /// Emit the diagnostic.
     pub fn emit(&mut self) {
         if self.cancelled() {
             return;
         }
 
-        self.handler.emit_db(&self);
+        self.0.handler.emit_db(&self);
         self.cancel();
     }
 
@@ -115,8 +128,8 @@
     /// Buffers the diagnostic for later emission, unless handler
     /// has disabled such buffering.
     pub fn buffer(mut self, buffered_diagnostics: &mut Vec<Diagnostic>) {
-        if self.handler.flags.dont_buffer_diagnostics ||
-            self.handler.flags.treat_err_as_bug.is_some()
+        if self.0.handler.flags.dont_buffer_diagnostics ||
+            self.0.handler.flags.treat_err_as_bug.is_some()
         {
             self.emit();
             return;
@@ -126,7 +139,7 @@
         // implements `Drop`.
         let diagnostic;
         unsafe {
-            diagnostic = std::ptr::read(&self.diagnostic);
+            diagnostic = std::ptr::read(&self.0.diagnostic);
             std::mem::forget(self);
         };
         // Logging here is useful to help track down where in logs an error was
@@ -144,7 +157,7 @@
         span: Option<S>,
     ) -> &mut Self {
         let span = span.map(|s| s.into()).unwrap_or_else(|| MultiSpan::new());
-        self.diagnostic.sub(level, message, span, None);
+        self.0.diagnostic.sub(level, message, span, None);
         self
     }
 
@@ -160,7 +173,7 @@
     /// locally in whichever way makes the most sense.
     pub fn delay_as_bug(&mut self) {
         self.level = Level::Bug;
-        self.handler.delay_as_bug(self.diagnostic.clone());
+        self.0.handler.delay_as_bug(self.0.diagnostic.clone());
         self.cancel();
     }
 
@@ -171,7 +184,7 @@
     /// then the snippet will just include that `Span`, which is
     /// called the primary span.
     pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
-        self.diagnostic.span_label(span, label);
+        self.0.diagnostic.span_label(span, label);
         self
     }
 
@@ -208,10 +221,10 @@
         suggestion: Vec<(Span, String)>,
         applicability: Applicability,
     ) -> &mut Self {
-        if !self.allow_suggestions {
+        if !self.0.allow_suggestions {
             return self
         }
-        self.diagnostic.multipart_suggestion(
+        self.0.diagnostic.multipart_suggestion(
             msg,
             suggestion,
             applicability,
@@ -225,10 +238,10 @@
         suggestion: Vec<(Span, String)>,
         applicability: Applicability,
     ) -> &mut Self {
-        if !self.allow_suggestions {
+        if !self.0.allow_suggestions {
             return self
         }
-        self.diagnostic.tool_only_multipart_suggestion(
+        self.0.diagnostic.tool_only_multipart_suggestion(
             msg,
             suggestion,
             applicability,
@@ -236,7 +249,6 @@
         self
     }
 
-
     pub fn span_suggestion(
         &mut self,
         sp: Span,
@@ -244,10 +256,10 @@
         suggestion: String,
         applicability: Applicability,
     ) -> &mut Self {
-        if !self.allow_suggestions {
+        if !self.0.allow_suggestions {
             return self
         }
-        self.diagnostic.span_suggestion(
+        self.0.diagnostic.span_suggestion(
             sp,
             msg,
             suggestion,
@@ -263,10 +275,10 @@
         suggestions: impl Iterator<Item = String>,
         applicability: Applicability,
     ) -> &mut Self {
-        if !self.allow_suggestions {
+        if !self.0.allow_suggestions {
             return self
         }
-        self.diagnostic.span_suggestions(
+        self.0.diagnostic.span_suggestions(
             sp,
             msg,
             suggestions,
@@ -282,10 +294,10 @@
         suggestion: String,
         applicability: Applicability,
     ) -> &mut Self {
-        if !self.allow_suggestions {
+        if !self.0.allow_suggestions {
             return self
         }
-        self.diagnostic.span_suggestion_short(
+        self.0.diagnostic.span_suggestion_short(
             sp,
             msg,
             suggestion,
@@ -301,10 +313,10 @@
         suggestion: String,
         applicability: Applicability,
     ) -> &mut Self {
-        if !self.allow_suggestions {
+        if !self.0.allow_suggestions {
             return self
         }
-        self.diagnostic.span_suggestion_hidden(
+        self.0.diagnostic.span_suggestion_hidden(
             sp,
             msg,
             suggestion,
@@ -320,10 +332,10 @@
         suggestion: String,
         applicability: Applicability,
     ) -> &mut Self {
-        if !self.allow_suggestions {
+        if !self.0.allow_suggestions {
             return self
         }
-        self.diagnostic.tool_only_span_suggestion(
+        self.0.diagnostic.tool_only_span_suggestion(
             sp,
             msg,
             suggestion,
@@ -336,7 +348,7 @@
     forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
 
     pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self {
-        self.allow_suggestions = allow;
+        self.0.allow_suggestions = allow;
         self
     }
 
@@ -359,19 +371,18 @@
 
     /// Creates a new `DiagnosticBuilder` with an already constructed
     /// diagnostic.
-    pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
-                         -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder {
+    pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> {
+        DiagnosticBuilder(Box::new(DiagnosticBuilderInner {
             handler,
             diagnostic,
             allow_suggestions: true,
-        }
+        }))
     }
 }
 
 impl<'a> Debug for DiagnosticBuilder<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.diagnostic.fmt(f)
+        self.0.diagnostic.fmt(f)
     }
 }
 
@@ -381,7 +392,7 @@
     fn drop(&mut self) {
         if !panicking() && !self.cancelled() {
             let mut db = DiagnosticBuilder::new(
-                self.handler,
+                self.0.handler,
                 Level::Bug,
                 "the following error was constructed but not emitted",
             );
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 77d373e..d238de2 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -146,12 +146,12 @@
             } else if self.label_right - self.span_left <= self.column_width {
                 // Attempt to fit the code window considering only the spans and labels.
                 let padding_left = (self.column_width - (self.label_right - self.span_left)) / 2;
-                self.computed_left = self.span_left - padding_left;
+                self.computed_left = self.span_left.saturating_sub(padding_left);
                 self.computed_right = self.computed_left + self.column_width;
             } else if self.span_right - self.span_left <= self.column_width {
                 // Attempt to fit the code window considering the spans and labels plus padding.
                 let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2;
-                self.computed_left = self.span_left - padding_left;
+                self.computed_left = self.span_left.saturating_sub(padding_left);
                 self.computed_right = self.computed_left + self.column_width;
             } else { // Mostly give up but still don't show the full line.
                 self.computed_left = self.span_left;
@@ -191,16 +191,25 @@
     fn should_show_explain(&self) -> bool {
         true
     }
-}
 
-impl Emitter for EmitterWriter {
-    fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) {
+    /// Formats the substitutions of the primary_span
+    ///
+    /// The are a lot of conditions to this method, but in short:
+    ///
+    /// * If the current `Diagnostic` has only one visible `CodeSuggestion`,
+    ///   we format the `help` suggestion depending on the content of the
+    ///   substitutions. In that case, we return the modified span only.
+    ///
+    /// * If the current `Diagnostic` has multiple suggestions,
+    ///   we return the original `primary_span` and the original suggestions.
+    fn primary_span_formatted<'a>(
+        &mut self,
+        db: &'a DiagnosticBuilder<'_>
+    ) -> (MultiSpan, &'a [CodeSuggestion]) {
         let mut primary_span = db.span.clone();
-        let mut children = db.children.clone();
-        let mut suggestions: &[_] = &[];
-
         if let Some((sugg, rest)) = db.suggestions.split_first() {
             if rest.is_empty() &&
+               // ^ if there is only one suggestion
                // don't display multi-suggestions as labels
                sugg.substitutions.len() == 1 &&
                // don't display multipart suggestions as labels
@@ -216,26 +225,167 @@
             {
                 let substitution = &sugg.substitutions[0].parts[0].snippet.trim();
                 let msg = if substitution.len() == 0 || sugg.style.hide_inline() {
-                    // This substitution is only removal or we explicitly don't want to show the
-                    // code inline, don't show it
+                    // This substitution is only removal OR we explicitly don't want to show the
+                    // code inline (`hide_inline`). Therefore, we don't show the substitution.
                     format!("help: {}", sugg.msg)
                 } else {
+                    // Show the default suggestion text with the substitution
                     format!("help: {}: `{}`", sugg.msg, substitution)
                 };
                 primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg);
+
+                // We return only the modified primary_span
+                (primary_span, &[])
             } else {
                 // if there are multiple suggestions, print them all in full
                 // to be consistent. We could try to figure out if we can
                 // make one (or the first one) inline, but that would give
                 // undue importance to a semi-random suggestion
-                suggestions = &db.suggestions;
+                (primary_span, &db.suggestions)
+            }
+        } else {
+            (primary_span, &db.suggestions)
+        }
+    }
+
+    // This does a small "fix" for multispans by looking to see if it can find any that
+    // point directly at <*macros>. Since these are often difficult to read, this
+    // will change the span to point at the use site.
+    fn fix_multispans_in_std_macros(&self,
+                                    source_map: &Option<Lrc<SourceMapperDyn>>,
+                                    span: &mut MultiSpan,
+                                    children: &mut Vec<SubDiagnostic>,
+                                    level: &Level,
+                                    backtrace: bool) {
+        let mut spans_updated = self.fix_multispan_in_std_macros(source_map, span, backtrace);
+        for child in children.iter_mut() {
+            spans_updated |= self.fix_multispan_in_std_macros(
+                                 source_map,
+                                 &mut child.span,
+                                 backtrace
+                             );
+        }
+        let msg = if level == &Error {
+            "this error originates in a macro outside of the current crate \
+             (in Nightly builds, run with -Z external-macro-backtrace \
+              for more info)".to_string()
+        } else {
+            "this warning originates in a macro outside of the current crate \
+             (in Nightly builds, run with -Z external-macro-backtrace \
+              for more info)".to_string()
+        };
+
+        if spans_updated {
+            children.push(SubDiagnostic {
+                level: Level::Note,
+                message: vec![
+                    (msg,
+                     Style::NoStyle),
+                ],
+                span: MultiSpan::new(),
+                render_span: None,
+            });
+        }
+    }
+
+    // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
+    // <*macros>. Since these locations are often difficult to read, we move these Spans from
+    // <*macros> to their corresponding use site.
+    fn fix_multispan_in_std_macros(&self,
+                                   source_map: &Option<Lrc<SourceMapperDyn>>,
+                                   span: &mut MultiSpan,
+                                   always_backtrace: bool) -> bool {
+        let mut spans_updated = false;
+
+        if let Some(ref sm) = source_map {
+            let mut before_after: Vec<(Span, Span)> = vec![];
+            let mut new_labels: Vec<(Span, String)> = vec![];
+
+            // First, find all the spans in <*macros> and point instead at their use site
+            for sp in span.primary_spans() {
+                if sp.is_dummy() {
+                    continue;
+                }
+                let call_sp = sm.call_span_if_macro(*sp);
+                if call_sp != *sp && !always_backtrace {
+                    before_after.push((*sp, call_sp));
+                }
+                let backtrace_len = sp.macro_backtrace().len();
+                for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() {
+                    // Only show macro locations that are local
+                    // and display them like a span_note
+                    if trace.def_site_span.is_dummy() {
+                        continue;
+                    }
+                    if always_backtrace {
+                        new_labels.push((trace.def_site_span,
+                                            format!("in this expansion of `{}`{}",
+                                                    trace.macro_decl_name,
+                                                    if backtrace_len > 2 {
+                                                        // if backtrace_len == 1 it'll be pointed
+                                                        // at by "in this macro invocation"
+                                                        format!(" (#{})", i + 1)
+                                                    } else {
+                                                        String::new()
+                                                    })));
+                    }
+                    // Check to make sure we're not in any <*macros>
+                    if !sm.span_to_filename(trace.def_site_span).is_macros() &&
+                        !trace.macro_decl_name.starts_with("desugaring of ") &&
+                        !trace.macro_decl_name.starts_with("#[") ||
+                        always_backtrace {
+                        new_labels.push((trace.call_site,
+                                            format!("in this macro invocation{}",
+                                                    if backtrace_len > 2 && always_backtrace {
+                                                        // only specify order when the macro
+                                                        // backtrace is multiple levels deep
+                                                        format!(" (#{})", i + 1)
+                                                    } else {
+                                                        String::new()
+                                                    })));
+                        if !always_backtrace {
+                            break;
+                        }
+                    }
+                }
+            }
+            for (label_span, label_text) in new_labels {
+                span.push_span_label(label_span, label_text);
+            }
+            for sp_label in span.span_labels() {
+                if sp_label.span.is_dummy() {
+                    continue;
+                }
+                if sm.span_to_filename(sp_label.span.clone()).is_macros() &&
+                    !always_backtrace
+                {
+                    let v = sp_label.span.macro_backtrace();
+                    if let Some(use_site) = v.last() {
+                        before_after.push((sp_label.span.clone(), use_site.call_site.clone()));
+                    }
+                }
+            }
+            // After we have them, make sure we replace these 'bad' def sites with their use sites
+            for (before, after) in before_after {
+                span.replace(before, after);
+                spans_updated = true;
             }
         }
 
-        self.fix_multispans_in_std_macros(&mut primary_span,
+        spans_updated
+    }
+}
+
+impl Emitter for EmitterWriter {
+    fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) {
+        let mut children = db.children.clone();
+        let (mut primary_span, suggestions) = self.primary_span_formatted(&db);
+
+        self.fix_multispans_in_std_macros(&self.sm,
+                                          &mut primary_span,
                                           &mut children,
                                           &db.level,
-                                          db.handler.flags.external_macro_backtrace);
+                                          db.handler().flags.external_macro_backtrace);
 
         self.emit_messages_default(&db.level,
                                    &db.styled_message(),
@@ -897,127 +1047,6 @@
         max
     }
 
-    // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of
-    // <*macros>. Since these locations are often difficult to read, we move these Spans from
-    // <*macros> to their corresponding use site.
-    fn fix_multispan_in_std_macros(&mut self,
-                                   span: &mut MultiSpan,
-                                   always_backtrace: bool) -> bool {
-        let mut spans_updated = false;
-
-        if let Some(ref sm) = self.sm {
-            let mut before_after: Vec<(Span, Span)> = vec![];
-            let mut new_labels: Vec<(Span, String)> = vec![];
-
-            // First, find all the spans in <*macros> and point instead at their use site
-            for sp in span.primary_spans() {
-                if sp.is_dummy() {
-                    continue;
-                }
-                let call_sp = sm.call_span_if_macro(*sp);
-                if call_sp != *sp && !always_backtrace {
-                    before_after.push((*sp, call_sp));
-                }
-                let backtrace_len = sp.macro_backtrace().len();
-                for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() {
-                    // Only show macro locations that are local
-                    // and display them like a span_note
-                    if trace.def_site_span.is_dummy() {
-                        continue;
-                    }
-                    if always_backtrace {
-                        new_labels.push((trace.def_site_span,
-                                            format!("in this expansion of `{}`{}",
-                                                    trace.macro_decl_name,
-                                                    if backtrace_len > 2 {
-                                                        // if backtrace_len == 1 it'll be pointed
-                                                        // at by "in this macro invocation"
-                                                        format!(" (#{})", i + 1)
-                                                    } else {
-                                                        String::new()
-                                                    })));
-                    }
-                    // Check to make sure we're not in any <*macros>
-                    if !sm.span_to_filename(trace.def_site_span).is_macros() &&
-                        !trace.macro_decl_name.starts_with("desugaring of ") &&
-                        !trace.macro_decl_name.starts_with("#[") ||
-                        always_backtrace {
-                        new_labels.push((trace.call_site,
-                                            format!("in this macro invocation{}",
-                                                    if backtrace_len > 2 && always_backtrace {
-                                                        // only specify order when the macro
-                                                        // backtrace is multiple levels deep
-                                                        format!(" (#{})", i + 1)
-                                                    } else {
-                                                        String::new()
-                                                    })));
-                        if !always_backtrace {
-                            break;
-                        }
-                    }
-                }
-            }
-            for (label_span, label_text) in new_labels {
-                span.push_span_label(label_span, label_text);
-            }
-            for sp_label in span.span_labels() {
-                if sp_label.span.is_dummy() {
-                    continue;
-                }
-                if sm.span_to_filename(sp_label.span.clone()).is_macros() &&
-                    !always_backtrace
-                {
-                    let v = sp_label.span.macro_backtrace();
-                    if let Some(use_site) = v.last() {
-                        before_after.push((sp_label.span.clone(), use_site.call_site.clone()));
-                    }
-                }
-            }
-            // After we have them, make sure we replace these 'bad' def sites with their use sites
-            for (before, after) in before_after {
-                span.replace(before, after);
-                spans_updated = true;
-            }
-        }
-
-        spans_updated
-    }
-
-    // This does a small "fix" for multispans by looking to see if it can find any that
-    // point directly at <*macros>. Since these are often difficult to read, this
-    // will change the span to point at the use site.
-    fn fix_multispans_in_std_macros(&mut self,
-                                    span: &mut MultiSpan,
-                                    children: &mut Vec<SubDiagnostic>,
-                                    level: &Level,
-                                    backtrace: bool) {
-        let mut spans_updated = self.fix_multispan_in_std_macros(span, backtrace);
-        for child in children.iter_mut() {
-            spans_updated |= self.fix_multispan_in_std_macros(&mut child.span, backtrace);
-        }
-        let msg = if level == &Error {
-            "this error originates in a macro outside of the current crate \
-             (in Nightly builds, run with -Z external-macro-backtrace \
-              for more info)".to_string()
-        } else {
-            "this warning originates in a macro outside of the current crate \
-             (in Nightly builds, run with -Z external-macro-backtrace \
-              for more info)".to_string()
-        };
-
-        if spans_updated {
-            children.push(SubDiagnostic {
-                level: Level::Note,
-                message: vec![
-                    (msg,
-                     Style::NoStyle),
-                ],
-                span: MultiSpan::new(),
-                render_span: None,
-            });
-        }
-    }
-
     /// Adds a left margin to every line but the first, given a padding length and the label being
     /// displayed, keeping the provided highlighting.
     fn msg_to_buffer(&self,
@@ -1115,15 +1144,18 @@
                 buffer.prepend(0, " ", Style::NoStyle);
             }
             draw_note_separator(&mut buffer, 0, max_line_num_len + 1);
-            let level_str = level.to_string();
-            if !level_str.is_empty() {
-                buffer.append(0, &level_str, Style::MainHeaderMsg);
-                buffer.append(0, ": ", Style::NoStyle);
+            if *level != Level::FailureNote {
+                let level_str = level.to_string();
+                if !level_str.is_empty() {
+                    buffer.append(0, &level_str, Style::MainHeaderMsg);
+                    buffer.append(0, ": ", Style::NoStyle);
+                }
             }
             self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None);
         } else {
             let level_str = level.to_string();
-            if !level_str.is_empty() {
+            // The failure note level itself does not provide any useful diagnostic information
+            if *level != Level::FailureNote && !level_str.is_empty() {
                 buffer.append(0, &level_str, Style::Level(level.clone()));
             }
             // only render error codes, not lint codes
@@ -1132,7 +1164,7 @@
                 buffer.append(0, &code, Style::Level(level.clone()));
                 buffer.append(0, "]", Style::Level(level.clone()));
             }
-            if !level_str.is_empty() {
+            if *level != Level::FailureNote && !level_str.is_empty() {
                 buffer.append(0, ": ", header_style);
             }
             for &(ref text, _) in msg.iter() {
@@ -1304,11 +1336,13 @@
                 };
 
                 let column_width = if let Some(width) = self.terminal_width {
-                    width
+                    width.saturating_sub(code_offset)
                 } else if self.ui_testing {
                     140
                 } else {
-                    term_size::dimensions().map(|(w, _)| w - code_offset).unwrap_or(140)
+                    term_size::dimensions()
+                        .map(|(w, _)| w.saturating_sub(code_offset))
+                        .unwrap_or(std::usize::MAX)
                 };
 
                 let margin = Margin::new(
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 6585633..8b543be 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -833,7 +833,7 @@
             Warning => "warning",
             Note => "note",
             Help => "help",
-            FailureNote => "",
+            FailureNote => "failure-note",
             Cancelled => panic!("Shouldn't call on cancelled error"),
         }
     }
@@ -845,3 +845,10 @@
         }
     }
 }
+
+#[macro_export]
+macro_rules! pluralise {
+    ($x:expr) => {
+        if $x != 1 { "s" } else { "" }
+    };
+}
diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml
index a931ad3..659c4c8 100644
--- a/src/librustc_incremental/Cargo.toml
+++ b/src/librustc_incremental/Cargo.toml
@@ -12,7 +12,7 @@
 [dependencies]
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
-rand = "0.6"
+rand = "0.7"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index 046fdc7..e08eeaf 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -27,7 +27,7 @@
 use rustc::ty::TyCtxt;
 use std::collections::BTreeSet;
 use syntax::ast;
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::{InternedString, Symbol, sym};
 use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED,
                  ATTR_EXPECTED_CGU_REUSE};
 
@@ -45,8 +45,8 @@
             .collect_and_partition_mono_items(LOCAL_CRATE)
             .1
             .iter()
-            .map(|cgu| format!("{}", cgu.name()))
-            .collect::<BTreeSet<String>>();
+            .map(|cgu| *cgu.name())
+            .collect::<BTreeSet<InternedString>>();
 
         let ams = AssertModuleSource {
             tcx,
@@ -61,7 +61,7 @@
 
 struct AssertModuleSource<'tcx> {
     tcx: TyCtxt<'tcx>,
-    available_cgus: BTreeSet<String>,
+    available_cgus: BTreeSet<InternedString>,
 }
 
 impl AssertModuleSource<'tcx> {
@@ -127,7 +127,7 @@
 
         debug!("mapping '{}' to cgu name '{}'", self.field(attr, MODULE), cgu_name);
 
-        if !self.available_cgus.contains(&cgu_name.as_str()[..]) {
+        if !self.available_cgus.contains(&cgu_name) {
             self.tcx.sess.span_err(attr.span,
                 &format!("no module named `{}` (mangled: {}). \
                           Available modules: {}",
@@ -135,7 +135,7 @@
                     cgu_name,
                     self.available_cgus
                         .iter()
-                        .cloned()
+                        .map(|cgu| cgu.as_str().to_string())
                         .collect::<Vec<_>>()
                         .join(", ")));
         }
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index 16b377d..f629310 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -34,3 +34,4 @@
 rustc_privacy = { path = "../librustc_privacy" }
 rustc_resolve = { path = "../librustc_resolve" }
 tempfile = "3.0.5"
+once_cell = "1"
diff --git a/src/librustc_interface/build.rs b/src/librustc_interface/build.rs
new file mode 100644
index 0000000..79a343e
--- /dev/null
+++ b/src/librustc_interface/build.rs
@@ -0,0 +1,4 @@
+fn main() {
+    println!("cargo:rerun-if-changed=build.rs");
+    println!("cargo:rerun-if-env-changed=RUSTC_INSTALL_BINDIR");
+}
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 24b4496..e8e8da6 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -34,14 +34,13 @@
 use rustc_resolve::{Resolver, ResolverArenas};
 use rustc_traits;
 use rustc_typeck as typeck;
-use syntax::{self, ast, diagnostics, visit};
+use syntax::{self, ast, visit};
 use syntax::early_buffered_lints::BufferedEarlyLint;
 use syntax::ext::base::{NamedSyntaxExtension, ExtCtxt};
 use syntax::mut_visit::MutVisitor;
 use syntax::parse::{self, PResult};
 use syntax::util::node_count::NodeCounter;
 use syntax::symbol::Symbol;
-use syntax::feature_gate::AttributeType;
 use syntax_pos::FileName;
 use syntax_ext;
 
@@ -219,7 +218,6 @@
 
 pub struct PluginInfo {
     syntax_exts: Vec<NamedSyntaxExtension>,
-    attributes: Vec<(Symbol, AttributeType)>,
 }
 
 pub fn register_plugins<'a>(
@@ -230,10 +228,12 @@
     crate_name: &str,
 ) -> Result<(ast::Crate, PluginInfo)> {
     krate = time(sess, "attributes injection", || {
-        syntax::attr::inject(krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr)
+        syntax_ext::cmdline_attrs::inject(
+            krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr
+        )
     });
 
-    let (mut krate, features) = syntax::config::features(
+    let (krate, features) = syntax::config::features(
         krate,
         &sess.parse_sess,
         sess.edition(),
@@ -268,16 +268,6 @@
         middle::recursion_limit::update_limits(sess, &krate);
     });
 
-    krate = time(sess, "crate injection", || {
-        let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s);
-        let (krate, name) =
-            syntax_ext::standard_library_imports::inject(krate, alt_std_name, sess.edition());
-        if let Some(name) = name {
-            sess.parse_sess.injected_crate_name.set(name);
-        }
-        krate
-    });
-
     let registrars = time(sess, "plugin loading", || {
         plugin::load::load_plugins(
             sess,
@@ -291,21 +281,6 @@
     let mut registry = Registry::new(sess, krate.span);
 
     time(sess, "plugin registration", || {
-        if sess.features_untracked().rustc_diagnostic_macros {
-            registry.register_macro(
-                "__diagnostic_used",
-                diagnostics::plugin::expand_diagnostic_used,
-            );
-            registry.register_macro(
-                "__register_diagnostic",
-                diagnostics::plugin::expand_register_diagnostic,
-            );
-            registry.register_macro(
-                "__build_diagnostic_array",
-                diagnostics::plugin::expand_build_diagnostic_array,
-            );
-        }
-
         for registrar in registrars {
             registry.args_hidden = Some(registrar.args);
             (registrar.fun)(&mut registry);
@@ -335,12 +310,9 @@
     }
 
     *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
-    *sess.plugin_attributes.borrow_mut() = attributes.clone();
+    *sess.plugin_attributes.borrow_mut() = attributes;
 
-    Ok((krate, PluginInfo {
-        syntax_exts,
-        attributes,
-    }))
+    Ok((krate, PluginInfo { syntax_exts }))
 }
 
 fn configure_and_expand_inner<'a>(
@@ -352,7 +324,6 @@
     crate_loader: &'a mut CrateLoader<'a>,
     plugin_info: PluginInfo,
 ) -> Result<(ast::Crate, Resolver<'a>)> {
-    let attributes = plugin_info.attributes;
     time(sess, "pre ast expansion lint checks", || {
         lint::check_ast_crate(
             sess,
@@ -370,6 +341,21 @@
         &resolver_arenas,
     );
     syntax_ext::register_builtin_macros(&mut resolver, sess.edition());
+
+    krate = time(sess, "crate injection", || {
+        let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s));
+        let (krate, name) = syntax_ext::standard_library_imports::inject(
+            krate,
+            &mut resolver,
+            &sess.parse_sess,
+            alt_std_name,
+        );
+        if let Some(name) = name {
+            sess.parse_sess.injected_crate_name.set(name);
+        }
+        krate
+    });
+
     syntax_ext::plugin_macro_defs::inject(
         &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition()
     );
@@ -530,7 +516,6 @@
             &krate,
             &sess.parse_sess,
             &sess.features_untracked(),
-            &attributes,
             sess.opts.unstable_features,
         );
     });
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index f007a0c..b81f814 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -43,17 +43,17 @@
 
 pub fn diagnostics_registry() -> Registry {
     let mut all_errors = Vec::new();
-    all_errors.extend_from_slice(&rustc::DIAGNOSTICS);
-    all_errors.extend_from_slice(&rustc_typeck::DIAGNOSTICS);
-    all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
-    all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc::error_codes::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc_typeck::error_codes::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc_resolve::error_codes::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc_privacy::error_codes::DIAGNOSTICS);
     // FIXME: need to figure out a way to get these back in here
     // all_errors.extend_from_slice(get_codegen_backend(sess).diagnostics());
-    all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
-    all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS);
-    all_errors.extend_from_slice(&rustc_plugin::DIAGNOSTICS);
-    all_errors.extend_from_slice(&rustc_mir::DIAGNOSTICS);
-    all_errors.extend_from_slice(&syntax::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc_metadata::error_codes::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc_passes::error_codes::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc_plugin::error_codes::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc_mir::error_codes::DIAGNOSTICS);
+    all_errors.extend_from_slice(&syntax::error_codes::DIAGNOSTICS);
 
     Registry::new(&all_errors)
 }
@@ -289,20 +289,39 @@
     backend
 }
 
-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");
+// This is used for rustdoc, but it uses similar machinery to codegen backend
+// loading, so we leave the code here. It is potentially useful for other tools
+// that want to invoke the rustc binary while linking to rustc as well.
+pub fn rustc_path<'a>() -> Option<&'a Path> {
+    static RUSTC_PATH: once_cell::sync::OnceCell<Option<PathBuf>> =
+        once_cell::sync::OnceCell::new();
 
+    const BIN_PATH: &str = env!("RUSTC_INSTALL_BINDIR");
+
+    RUSTC_PATH.get_or_init(|| get_rustc_path_inner(BIN_PATH)).as_ref().map(|v| &**v)
+}
+
+fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
+    sysroot_candidates().iter()
+        .filter_map(|sysroot| {
+            let candidate = sysroot.join(bin_path).join(if cfg!(target_os = "windows") {
+                "rustc.exe"
+            } else {
+                "rustc"
+            });
+            if candidate.exists() {
+                Some(candidate)
+            } else {
+                None
+            }
+        })
+        .next()
+}
+
+fn sysroot_candidates() -> Vec<PathBuf> {
     let target = session::config::host_triple();
     let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()];
-    let path = current_dll_path()
-        .and_then(|s| s.canonicalize().ok());
+    let path = current_dll_path().and_then(|s| s.canonicalize().ok());
     if let Some(dll) = path {
         // use `parent` twice to chop off the file name and then also the
         // directory containing the dll which should be either `lib` or `bin`.
@@ -327,69 +346,7 @@
         }
     }
 
-    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);
-        }
-    }
+    return sysroot_candidates;
 
     #[cfg(unix)]
     fn current_dll_path() -> Option<PathBuf> {
@@ -459,6 +416,85 @@
     }
 }
 
+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(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
     use std::hash::Hasher;
 
diff --git a/src/librustc_lexer/Cargo.toml b/src/librustc_lexer/Cargo.toml
index 0dbcda6..950771f0 100644
--- a/src/librustc_lexer/Cargo.toml
+++ b/src/librustc_lexer/Cargo.toml
@@ -2,14 +2,20 @@
 authors = ["The Rust Project Developers"]
 name = "rustc_lexer"
 version = "0.1.0"
+license = "MIT OR Apache-2.0"
 edition = "2018"
 
-# Note that this crate purposefully does not depend on other rustc crates
-[dependencies]
-unicode-xid = { version = "0.1.0", optional = true }
+repository = "https://github.com/rust-lang/rust/"
+description = """
+Rust lexer used by rustc. No stability guarantees are provided.
+"""
 
 # Note: do not remove this blank `[lib]` section.
 # This will be used when publishing this crate as `rustc-ap-rustc_lexer`.
 [lib]
 doctest = false
 name = "rustc_lexer"
+
+# Note that this crate purposefully does not depend on other rustc crates
+[dependencies]
+unicode-xid = "0.2.0"
diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs
index 41b47be..30a5175 100644
--- a/src/librustc_lexer/src/lib.rs
+++ b/src/librustc_lexer/src/lib.rs
@@ -1,6 +1,5 @@
-// We want to be able to build this crate with a stable compiler, so feature
-// flags should be optional.
-#![cfg_attr(not(feature = "unicode-xid"), feature(unicode_internals))]
+// We want to be able to build this crate with a stable compiler, so no
+// `#![feature]` attributes should be added.
 
 mod cursor;
 pub mod unescape;
@@ -103,6 +102,62 @@
     })
 }
 
+// See [UAX #31](http://unicode.org/reports/tr31) for definitions of these
+// classes.
+
+/// True if `c` is considered a whitespace according to Rust language definition.
+pub fn is_whitespace(c: char) -> bool {
+    // This is Pattern_White_Space.
+    //
+    // Note that this set is stable (ie, it doesn't change with different
+    // Unicode versions), so it's ok to just hard-code the values.
+
+    match c {
+        // Usual ASCII suspects
+        | '\u{0009}' // \t
+        | '\u{000A}' // \n
+        | '\u{000B}' // vertical tab
+        | '\u{000C}' // form feed
+        | '\u{000D}' // \r
+        | '\u{0020}' // space
+
+        // NEXT LINE from latin1
+        | '\u{0085}'
+
+        // Bidi markers
+        | '\u{200E}' // LEFT-TO-RIGHT MARK
+        | '\u{200F}' // RIGHT-TO-LEFT MARK
+
+        // Dedicated whitespace characters from Unicode
+        | '\u{2028}' // LINE SEPARATOR
+        | '\u{2029}' // PARAGRAPH SEPARATOR
+            => true,
+        _ => false,
+    }
+}
+
+/// True if `c` is valid as a first character of an identifier.
+pub fn is_id_start(c: char) -> bool {
+    // This is XID_Start OR '_' (which formally is not a XID_Start).
+    // We also add fast-path for ascii idents
+    ('a' <= c && c <= 'z')
+        || ('A' <= c && c <= 'Z')
+        || c == '_'
+        || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c))
+}
+
+/// True if `c` is valid as a non-first character of an identifier.
+pub fn is_id_continue(c: char) -> bool {
+    // This is exactly XID_Continue.
+    // We also add fast-path for ascii idents
+    ('a' <= c && c <= 'z')
+        || ('A' <= c && c <= 'Z')
+        || ('0' <= c && c <= '9')
+        || c == '_'
+        || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c))
+}
+
+
 impl Cursor<'_> {
     fn advance_token(&mut self) -> Token {
         let first_char = self.bump().unwrap();
@@ -112,9 +167,9 @@
                 '*' => self.block_comment(),
                 _ => Slash,
             },
-            c if character_properties::is_whitespace(c) => self.whitespace(),
+            c if is_whitespace(c) => self.whitespace(),
             'r' => match (self.nth_char(0), self.nth_char(1)) {
-                ('#', c1) if character_properties::is_id_start(c1) => self.raw_ident(),
+                ('#', c1) if is_id_start(c1) => self.raw_ident(),
                 ('#', _) | ('"', _) => {
                     let (n_hashes, started, terminated) = self.raw_double_quoted_string();
                     let suffix_start = self.len_consumed();
@@ -159,7 +214,7 @@
                 }
                 _ => self.ident(),
             },
-            c if character_properties::is_id_start(c) => self.ident(),
+            c if is_id_start(c) => self.ident(),
             c @ '0'..='9' => {
                 let literal_kind = self.number(c);
                 let suffix_start = self.len_consumed();
@@ -247,8 +302,8 @@
     }
 
     fn whitespace(&mut self) -> TokenKind {
-        debug_assert!(character_properties::is_whitespace(self.prev()));
-        while character_properties::is_whitespace(self.nth_char(0)) {
+        debug_assert!(is_whitespace(self.prev()));
+        while is_whitespace(self.nth_char(0)) {
             self.bump();
         }
         Whitespace
@@ -258,19 +313,19 @@
         debug_assert!(
             self.prev() == 'r'
                 && self.nth_char(0) == '#'
-                && character_properties::is_id_start(self.nth_char(1))
+                && is_id_start(self.nth_char(1))
         );
         self.bump();
         self.bump();
-        while character_properties::is_id_continue(self.nth_char(0)) {
+        while is_id_continue(self.nth_char(0)) {
             self.bump();
         }
         RawIdent
     }
 
     fn ident(&mut self) -> TokenKind {
-        debug_assert!(character_properties::is_id_start(self.prev()));
-        while character_properties::is_id_continue(self.nth_char(0)) {
+        debug_assert!(is_id_start(self.prev()));
+        while is_id_continue(self.nth_char(0)) {
             self.bump();
         }
         Ident
@@ -315,7 +370,7 @@
             // integer literal followed by field/method access or a range pattern
             // (`0..2` and `12.foo()`)
             '.' if self.nth_char(1) != '.'
-                && !character_properties::is_id_start(self.nth_char(1)) =>
+                && !is_id_start(self.nth_char(1)) =>
             {
                 // might have stuff after the ., and if it does, it needs to start
                 // with a number
@@ -345,7 +400,7 @@
     fn lifetime_or_char(&mut self) -> TokenKind {
         debug_assert!(self.prev() == '\'');
         let mut starts_with_number = false;
-        if (character_properties::is_id_start(self.nth_char(0))
+        if (is_id_start(self.nth_char(0))
             || self.nth_char(0).is_digit(10) && {
                 starts_with_number = true;
                 true
@@ -353,7 +408,7 @@
             && self.nth_char(1) != '\''
         {
             self.bump();
-            while character_properties::is_id_continue(self.nth_char(0)) {
+            while is_id_continue(self.nth_char(0)) {
                 self.bump();
             }
 
@@ -495,66 +550,13 @@
     }
 
     fn eat_literal_suffix(&mut self) {
-        if !character_properties::is_id_start(self.nth_char(0)) {
+        if !is_id_start(self.nth_char(0)) {
             return;
         }
         self.bump();
 
-        while character_properties::is_id_continue(self.nth_char(0)) {
+        while is_id_continue(self.nth_char(0)) {
             self.bump();
         }
     }
 }
-
-pub mod character_properties {
-    // this is Pattern_White_Space
-    #[cfg(feature = "unicode-xid")]
-    pub fn is_whitespace(c: char) -> bool {
-        match c {
-            '\u{0009}' | '\u{000A}' | '\u{000B}' | '\u{000C}' | '\u{000D}' | '\u{0020}'
-            | '\u{0085}' | '\u{200E}' | '\u{200F}' | '\u{2028}' | '\u{2029}' => true,
-            _ => false,
-        }
-    }
-
-    #[cfg(not(feature = "unicode-xid"))]
-    pub fn is_whitespace(c: char) -> bool {
-        core::unicode::property::Pattern_White_Space(c)
-    }
-
-    // this is XID_Start OR '_' (which formally is not a XID_Start)
-    #[cfg(feature = "unicode-xid")]
-    pub fn is_id_start(c: char) -> bool {
-        ('a' <= c && c <= 'z')
-            || ('A' <= c && c <= 'Z')
-            || c == '_'
-            || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c))
-    }
-
-    #[cfg(not(feature = "unicode-xid"))]
-    pub fn is_id_start(c: char) -> bool {
-        ('a' <= c && c <= 'z')
-            || ('A' <= c && c <= 'Z')
-            || c == '_'
-            || (c > '\x7f' && c.is_xid_start())
-    }
-
-    // this is XID_Continue
-    #[cfg(feature = "unicode-xid")]
-    pub fn is_id_continue(c: char) -> bool {
-        ('a' <= c && c <= 'z')
-            || ('A' <= c && c <= 'Z')
-            || ('0' <= c && c <= '9')
-            || c == '_'
-            || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c))
-    }
-
-    #[cfg(not(feature = "unicode-xid"))]
-    pub fn is_id_continue(c: char) -> bool {
-        ('a' <= c && c <= 'z')
-            || ('A' <= c && c <= 'Z')
-            || ('0' <= c && c <= '9')
-            || c == '_'
-            || (c > '\x7f' && c.is_xid_continue())
-    }
-}
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 26e7b78..cf19a9e 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -669,6 +669,22 @@
     }
 }
 
+fn lint_deprecated_attr(
+    cx: &EarlyContext<'_>,
+    attr: &ast::Attribute,
+    msg: &str,
+    suggestion: Option<&str>,
+) {
+    cx.struct_span_lint(DEPRECATED, attr.span, &msg)
+        .span_suggestion_short(
+            attr.span,
+            suggestion.unwrap_or("remove this attribute"),
+            String::new(),
+            Applicability::MachineApplicable
+        )
+        .emit();
+}
+
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
         for &&(n, _, _, ref g) in &self.depr_attrs {
@@ -679,18 +695,15 @@
                                              _) = g {
                     let msg = format!("use of deprecated attribute `{}`: {}. See {}",
                                       name, reason, link);
-                    let mut err = cx.struct_span_lint(DEPRECATED, attr.span, &msg);
-                    err.span_suggestion_short(
-                        attr.span,
-                        suggestion.unwrap_or("remove this attribute"),
-                        String::new(),
-                        Applicability::MachineApplicable
-                    );
-                    err.emit();
+                    lint_deprecated_attr(cx, attr, &msg, suggestion);
                 }
                 return;
             }
         }
+        if attr.check_name(sym::no_start) || attr.check_name(sym::crate_id) {
+            let msg = format!("use of deprecated attribute `{}`: no longer used.", attr.path);
+            lint_deprecated_attr(cx, attr, &msg, None);
+        }
     }
 }
 
@@ -772,7 +785,7 @@
     }
 
     fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
-        let arm_span = arm.pats[0].span.with_hi(arm.body.span.hi());
+        let arm_span = arm.pat.span.with_hi(arm.body.span.hi());
         self.warn_if_doc(cx, arm_span, "match arms", false, &arm.attrs);
     }
 
diff --git a/src/librustc_lint/error_codes.rs b/src/librustc_lint/error_codes.rs
index d7c39b7..ea2e1d9 100644
--- a/src/librustc_lint/error_codes.rs
+++ b/src/librustc_lint/error_codes.rs
@@ -1,5 +1,4 @@
-use syntax::register_diagnostics;
-
-register_diagnostics! {
+syntax::register_diagnostics! {
+;
     E0721, // `await` keyword
 }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 2783316..0e05401 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -15,7 +15,6 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(nll)]
-#![feature(rustc_diagnostic_macros)]
 
 #![recursion_limit="256"]
 
@@ -436,7 +435,12 @@
             id: LintId::of(INDIRECT_STRUCTURAL_MATCH),
             reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
             edition: None,
-        }
+        },
+        FutureIncompatibleInfo {
+            id: LintId::of(SOFT_UNSTABLE),
+            reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
+            edition: None,
+        },
         ]);
 
     // Register renamed and removed lints.
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 217e10a..3b8c06b 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -624,7 +624,7 @@
                     AdtKind::Struct => {
                         if !def.repr.c() && !def.repr.transparent() {
                             return FfiUnsafe {
-                                ty: ty,
+                                ty,
                                 reason: "this struct has unspecified layout",
                                 help: Some("consider adding a `#[repr(C)]` or \
                                             `#[repr(transparent)]` attribute to this struct"),
@@ -633,7 +633,7 @@
 
                         if def.non_enum_variant().fields.is_empty() {
                             return FfiUnsafe {
-                                ty: ty,
+                                ty,
                                 reason: "this struct has no fields",
                                 help: Some("consider adding a member to this struct"),
                             };
@@ -669,7 +669,7 @@
                     AdtKind::Union => {
                         if !def.repr.c() && !def.repr.transparent() {
                             return FfiUnsafe {
-                                ty: ty,
+                                ty,
                                 reason: "this union has unspecified layout",
                                 help: Some("consider adding a `#[repr(C)]` or \
                                             `#[repr(transparent)]` attribute to this union"),
@@ -678,7 +678,7 @@
 
                         if def.non_enum_variant().fields.is_empty() {
                             return FfiUnsafe {
-                                ty: ty,
+                                ty,
                                 reason: "this union has no fields",
                                 help: Some("consider adding a field to this union"),
                             };
@@ -721,7 +721,7 @@
                             // Special-case types like `Option<extern fn()>`.
                             if !is_repr_nullable_ptr(cx, ty, def, substs) {
                                 return FfiUnsafe {
-                                    ty: ty,
+                                    ty,
                                     reason: "enum has no representation hint",
                                     help: Some("consider adding a `#[repr(C)]`, \
                                                 `#[repr(transparent)]`, or integer `#[repr(...)]` \
@@ -750,7 +750,7 @@
                                     }
                                     FfiPhantom(..) => {
                                         return FfiUnsafe {
-                                            ty: ty,
+                                            ty,
                                             reason: "this enum contains a PhantomData field",
                                             help: None,
                                         };
@@ -764,13 +764,13 @@
             }
 
             ty::Char => FfiUnsafe {
-                ty: ty,
+                ty,
                 reason: "the `char` type has no C equivalent",
                 help: Some("consider using `u32` or `libc::wchar_t` instead"),
             },
 
             ty::Int(ast::IntTy::I128) | ty::Uint(ast::UintTy::U128) => FfiUnsafe {
-                ty: ty,
+                ty,
                 reason: "128-bit integers don't currently have a known stable ABI",
                 help: None,
             },
@@ -779,25 +779,25 @@
             ty::Bool | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Never => FfiSafe,
 
             ty::Slice(_) => FfiUnsafe {
-                ty: ty,
+                ty,
                 reason: "slices have no C equivalent",
                 help: Some("consider using a raw pointer instead"),
             },
 
             ty::Dynamic(..) => FfiUnsafe {
-                ty: ty,
+                ty,
                 reason: "trait objects have no C equivalent",
                 help: None,
             },
 
             ty::Str => FfiUnsafe {
-                ty: ty,
+                ty,
                 reason: "string slices have no C equivalent",
                 help: Some("consider using `*const u8` and a length instead"),
             },
 
             ty::Tuple(..) => FfiUnsafe {
-                ty: ty,
+                ty,
                 reason: "tuples have unspecified layout",
                 help: Some("consider using a struct instead"),
             },
@@ -811,7 +811,7 @@
                 match sig.abi() {
                     Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => {
                         return FfiUnsafe {
-                            ty: ty,
+                            ty,
                             reason: "this function pointer has Rust-specific calling convention",
                             help: Some("consider using an `extern fn(...) -> ...` \
                                         function pointer instead"),
@@ -855,11 +855,76 @@
             ty::UnnormalizedProjection(..) |
             ty::Projection(..) |
             ty::Opaque(..) |
-            ty::FnDef(..) => bug!("Unexpected type in foreign function"),
+            ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty),
+        }
+    }
+
+    fn emit_ffi_unsafe_type_lint(
+        &mut self,
+        ty: Ty<'tcx>,
+        sp: Span,
+        note: &str,
+        help: Option<&str>,
+    ) {
+        let mut diag = self.cx.struct_span_lint(
+            IMPROPER_CTYPES,
+            sp,
+            &format!("`extern` block uses type `{}`, which is not FFI-safe", ty),
+        );
+        diag.span_label(sp, "not FFI-safe");
+        if let Some(help) = help {
+            diag.help(help);
+        }
+        diag.note(note);
+        if let ty::Adt(def, _) = ty.sty {
+            if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) {
+                diag.span_note(sp, "type defined here");
+            }
+        }
+        diag.emit();
+    }
+
+    fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
+        use crate::rustc::ty::TypeFoldable;
+
+        struct ProhibitOpaqueTypes<'tcx> {
+            ty: Option<Ty<'tcx>>,
+        };
+
+        impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> {
+            fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
+                if let ty::Opaque(..) = ty.sty {
+                    self.ty = Some(ty);
+                    true
+                } else {
+                    ty.super_visit_with(self)
+                }
+            }
+        }
+
+        let mut visitor = ProhibitOpaqueTypes { ty: None };
+        ty.visit_with(&mut visitor);
+        if let Some(ty) = visitor.ty {
+            self.emit_ffi_unsafe_type_lint(
+                ty,
+                sp,
+                "opaque types have no C equivalent",
+                None,
+            );
+            true
+        } else {
+            false
         }
     }
 
     fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
+        // We have to check for opaque types before `normalize_erasing_regions`,
+        // which will replace opaque types with their underlying concrete type.
+        if self.check_for_opaque_ty(sp, ty) {
+            // We've already emitted an error due to an opaque type.
+            return;
+        }
+
         // it is only OK to use this function because extern fns cannot have
         // any generic types right now:
         let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
@@ -867,24 +932,10 @@
         match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
             FfiResult::FfiSafe => {}
             FfiResult::FfiPhantom(ty) => {
-                self.cx.span_lint(IMPROPER_CTYPES,
-                                  sp,
-                                  &format!("`extern` block uses type `{}` which is not FFI-safe: \
-                                            composed only of PhantomData", ty));
+                self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None);
             }
-            FfiResult::FfiUnsafe { ty: unsafe_ty, reason, help } => {
-                let msg = format!("`extern` block uses type `{}` which is not FFI-safe: {}",
-                                  unsafe_ty, reason);
-                let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg);
-                if let Some(s) = help {
-                    diag.help(s);
-                }
-                if let ty::Adt(def, _) = unsafe_ty.sty {
-                    if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) {
-                        diag.span_note(sp, "type defined here");
-                    }
-                }
-                diag.emit();
+            FfiResult::FfiUnsafe { ty, reason, help } => {
+                self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
             }
         }
     }
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 90e4677..c397509 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -370,7 +370,8 @@
                                      right_pos: Option<BytePos>) {
         match value.node {
             ast::ExprKind::Paren(ref inner) => {
-                if !Self::is_expr_parens_necessary(inner, followed_by_block) {
+                if !Self::is_expr_parens_necessary(inner, followed_by_block) &&
+                    value.attrs.is_empty() {
                     let expr_text = if let Ok(snippet) = cx.sess().source_map()
                         .span_to_snippet(value.span) {
                             snippet
@@ -398,18 +399,37 @@
         }
     }
 
-    fn check_unused_parens_pat(&self,
-                                cx: &EarlyContext<'_>,
-                                value: &ast::Pat,
-                                msg: &str) {
-        if let ast::PatKind::Paren(_) = value.node {
+    fn check_unused_parens_pat(
+        &self,
+        cx: &EarlyContext<'_>,
+        value: &ast::Pat,
+        avoid_or: bool,
+        avoid_mut: bool,
+    ) {
+        use ast::{PatKind, BindingMode::ByValue, Mutability::Mutable};
+
+        if let PatKind::Paren(inner) = &value.node {
+            match inner.node {
+                // The lint visitor will visit each subpattern of `p`. We do not want to lint
+                // any range pattern no matter where it occurs in the pattern. For something like
+                // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume
+                // that if there are unnecessary parens they serve a purpose of readability.
+                PatKind::Range(..) => return,
+                // Avoid `p0 | .. | pn` if we should.
+                PatKind::Or(..) if avoid_or => return,
+                // Avoid `mut x` and `mut x @ p` if we should:
+                PatKind::Ident(ByValue(Mutable), ..) if avoid_mut => return,
+                // Otherwise proceed with linting.
+                _ => {}
+            }
+
             let pattern_text = if let Ok(snippet) = cx.sess().source_map()
                 .span_to_snippet(value.span) {
                     snippet
                 } else {
                     pprust::pat_to_string(value)
                 };
-            Self::remove_outer_parens(cx, value.span, &pattern_text, msg, (false, false));
+            Self::remove_outer_parens(cx, value.span, &pattern_text, "pattern", (false, false));
         }
     }
 
@@ -474,6 +494,11 @@
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         use syntax::ast::ExprKind::*;
         let (value, msg, followed_by_block, left_pos, right_pos) = match e.node {
+            Let(ref pat, ..) => {
+                self.check_unused_parens_pat(cx, pat, false, false);
+                return;
+            }
+
             If(ref cond, ref block, ..) => {
                 let left = e.span.lo() + syntax_pos::BytePos(2);
                 let right = block.span.lo();
@@ -486,7 +511,8 @@
                 (cond, "`while` condition", true, Some(left), Some(right))
             },
 
-            ForLoop(_, ref cond, ref block, ..) => {
+            ForLoop(ref pat, ref cond, ref block, ..) => {
+                self.check_unused_parens_pat(cx, pat, false, false);
                 (cond, "`for` head expression", true, None, Some(block.span.lo()))
             }
 
@@ -531,26 +557,44 @@
     }
 
     fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
-        use ast::PatKind::{Paren, Range};
-        // The lint visitor will visit each subpattern of `p`. We do not want to lint any range
-        // pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there
-        // is a recursive `check_pat` on `a` and `b`, but we will assume that if there are
-        // unnecessary parens they serve a purpose of readability.
-        if let Paren(ref pat) = p.node {
-            match pat.node {
-                Range(..) => {}
-                _ => self.check_unused_parens_pat(cx, &p, "pattern")
-            }
+        use ast::{PatKind::*, Mutability};
+        match &p.node {
+            // Do not lint on `(..)` as that will result in the other arms being useless.
+            Paren(_)
+            // The other cases do not contain sub-patterns.
+            | Wild | Rest | Lit(..) | Mac(..) | Range(..) | Ident(.., None) | Path(..) => return,
+            // These are list-like patterns; parens can always be removed.
+            TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
+                self.check_unused_parens_pat(cx, p, false, false);
+            },
+            Struct(_, fps, _) => for f in fps {
+                self.check_unused_parens_pat(cx, &f.pat, false, false);
+            },
+            // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
+            Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false),
+            // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
+            // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
+            Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Immutable),
         }
     }
 
     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
         if let ast::StmtKind::Local(ref local) = s.node {
+            self.check_unused_parens_pat(cx, &local.pat, false, false);
+
             if let Some(ref value) = local.init {
                 self.check_unused_parens_expr(cx, &value, "assigned value", false, None, None);
             }
         }
     }
+
+    fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
+        self.check_unused_parens_pat(cx, &param.pat, true, false);
+    }
+
+    fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
+        self.check_unused_parens_pat(cx, &arm.pat, false, false);
+    }
 }
 
 declare_lint! {
@@ -575,24 +619,19 @@
             }
 
             // Trigger the lint if the nested item is a non-self single item
-            let node_ident;
-            match items[0].0.kind {
+            let node_name = match items[0].0.kind {
                 ast::UseTreeKind::Simple(rename, ..) => {
                     let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
                     if orig_ident.name == kw::SelfLower {
                         return;
                     }
-                    node_ident = rename.unwrap_or(orig_ident);
+                    rename.unwrap_or(orig_ident).name
                 }
-                ast::UseTreeKind::Glob => {
-                    node_ident = ast::Ident::from_str("*");
-                }
-                ast::UseTreeKind::Nested(_) => {
-                    return;
-                }
-            }
+                ast::UseTreeKind::Glob => Symbol::intern("*"),
+                ast::UseTreeKind::Nested(_) => return,
+            };
 
-            let msg = format!("braces around {} is unnecessary", node_ident.name);
+            let msg = format!("braces around {} is unnecessary", node_name);
             cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &msg);
         }
     }
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index 40ddd65..62a3757 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -54,7 +54,7 @@
     // LLVM are compiled the same way, but for us that's typically the case.
     //
     // We *want* detect this cross compiling situation by asking llvm-config
-    // what it's host-target is. If that's not the TARGET, then we're cross
+    // what its host-target is. If that's not the TARGET, then we're cross
     // compiling. Unfortunately `llvm-config` seems either be buggy, or we're
     // misconfiguring it, because the `i686-pc-windows-gnu` build of LLVM will
     // report itself with a `--host-target` of `x86_64-pc-windows-gnu`. This
@@ -62,7 +62,7 @@
     // havoc ensues.
     //
     // In any case, if we're cross compiling, this generally just means that we
-    // can't trust all the output of llvm-config becaues it might be targeted
+    // can't trust all the output of llvm-config because it might be targeted
     // for the host rather than the target. As a result a bunch of blocks below
     // are gated on `if !is_crossed`
     let target = env::var("TARGET").expect("TARGET was not set");
@@ -166,7 +166,7 @@
 
     let (llvm_kind, llvm_link_arg) = detect_llvm_link();
 
-    // Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then
+    // Link in all LLVM libraries, if we're using the "wrong" llvm-config then
     // we don't pick up system libs because unfortunately they're for the host
     // of llvm-config, not the target that we're attempting to link.
     let mut cmd = Command::new(&llvm_config);
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
index b8c7b7c..73720d8 100644
--- a/src/librustc_lsan/build.rs
+++ b/src/librustc_lsan/build.rs
@@ -4,6 +4,10 @@
 use cmake::Config;
 
 fn main() {
+    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
+    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
+        return;
+    }
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
         build_helper::restore_library_path();
 
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index d6450f0..a1e3bbc 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -444,7 +444,8 @@
             .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
         LoadedMacro::MacroDef(ast::Item {
-            ident: ast::Ident::from_str(&name.as_str()),
+            // FIXME: cross-crate hygiene
+            ident: ast::Ident::with_dummy_span(name.as_symbol()),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs.iter().cloned().collect(),
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 75d7261..34c84b1 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -489,7 +489,11 @@
 
     fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
         // DefIndex's in root.proc_macro_data have a one-to-one correspondence
-        // with items in 'raw_proc_macros'
+        // with items in 'raw_proc_macros'.
+        // NOTE: If you update the order of macros in 'proc_macro_data' for any reason,
+        // you must also update src/libsyntax_ext/proc_macro_harness.rs
+        // Failing to do so will result in incorrect data being associated
+        // with proc macros when deserialized.
         let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap();
         &self.raw_proc_macros.unwrap()[pos]
     }
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index db21240..f430f01 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1354,7 +1354,7 @@
         let def_id = self.tcx.hir().local_def_id(macro_def.hir_id);
         Entry {
             kind: EntryKind::MacroDef(self.lazy(MacroDef {
-                body: pprust::tokens_to_string(macro_def.body.clone()),
+                body: pprust::tts_to_string(macro_def.body.clone()),
                 legacy: macro_def.legacy,
             })),
             visibility: self.lazy(ty::Visibility::Public),
diff --git a/src/librustc_metadata/error_codes.rs b/src/librustc_metadata/error_codes.rs
index 0708a62..cd8e95e 100644
--- a/src/librustc_metadata/error_codes.rs
+++ b/src/librustc_metadata/error_codes.rs
@@ -1,6 +1,4 @@
-use syntax::{register_diagnostics, register_long_diagnostics};
-
-register_long_diagnostics! {
+syntax::register_diagnostics! {
 E0454: r##"
 A link name was given with an empty name. Erroneous code example:
 
@@ -84,10 +82,7 @@
 (through Cargo or the `-L` option of rustc example). Plugins are crates as
 well, and you link to them the same way.
 "##,
-
-}
-
-register_diagnostics! {
+;
     E0456, // plugin `..` is not available for triple `..`
     E0457, // plugin `..` only found in rlib format, but must be available...
     E0514, // metadata version mismatch
@@ -97,5 +92,6 @@
     E0464, // multiple matching crates for `..`
     E0465, // multiple .. candidates for `..` found
     E0519, // local crate and dependency have same (crate-name, disambiguator)
-    E0523, // two dependencies have same (crate-name, disambiguator) but different SVH
+    // two dependencies have same (crate-name, disambiguator) but different SVH
+    E0523,
 }
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index c96d02d..e6104e6 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -8,7 +8,6 @@
 #![feature(nll)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
-#![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(slice_patterns)]
 #![feature(specialization)]
@@ -23,7 +22,7 @@
 #[macro_use]
 extern crate rustc_data_structures;
 
-mod error_codes;
+pub mod error_codes;
 
 mod index;
 mod encoder;
@@ -68,5 +67,3 @@
         sess.unwrap().abort_if_errors();
     }
 }
-
-__build_diagnostic_array! { librustc_metadata, DIAGNOSTICS }
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index 66971bb..ada1a8c 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -8,7 +8,7 @@
 use syntax::attr;
 use syntax::source_map::Span;
 use syntax::feature_gate::{self, GateIssue};
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::{kw, sym, Symbol};
 use syntax::{span_err, struct_span_err};
 
 pub fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
@@ -132,7 +132,7 @@
 
 impl Collector<'tcx> {
     fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLibrary) {
-        if lib.name.as_ref().map(|s| s.as_str().is_empty()).unwrap_or(false) {
+        if lib.name.as_ref().map(|&s| s == kw::Invalid).unwrap_or(false) {
             match span {
                 Some(span) => {
                     struct_span_err!(self.tcx.sess, span, E0454,
@@ -159,7 +159,7 @@
                                            sym::link_cfg,
                                            span.unwrap(),
                                            GateIssue::Language,
-                                           "is feature gated");
+                                           "is unstable");
         }
         if lib.kind == cstore::NativeStaticNobundle &&
            !self.tcx.features().static_nobundle {
@@ -167,7 +167,7 @@
                                            sym::static_nobundle,
                                            span.unwrap_or_else(|| syntax_pos::DUMMY_SP),
                                            GateIssue::Language,
-                                           "kind=\"static-nobundle\" is feature gated");
+                                           "kind=\"static-nobundle\" is unstable");
         }
         self.libs.push(lib);
     }
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 21008c7..0691390 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -15,14 +15,15 @@
 dot = { path = "../libgraphviz", package = "graphviz" }
 log = "0.4"
 log_settings = "0.1.1"
-polonius-engine  = "0.9.0"
+polonius-engine  = "0.10.0"
 rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
+rustc_lexer = { path = "../librustc_lexer" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-byteorder = { version = "1.1", features = ["i128"] }
+byteorder = { version = "1.3" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index c9e6e7f..db19cbc 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -317,7 +317,7 @@
         // so extract `temp`.
         let temp = if let &mir::Place {
             base: mir::PlaceBase::Local(temp),
-            projection: None,
+            projection: box [],
         } = assigned_place {
             temp
         } else {
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index 247783c..81359c6 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -2,8 +2,8 @@
 use rustc::hir::def_id::DefId;
 use rustc::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local,
-    LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, Projection, PlaceRef,
-    ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
+    LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue,
+    Statement, StatementKind, TerminatorKind, VarBindingForm,
 };
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashSet;
@@ -98,7 +98,7 @@
                 &self.describe_place_with_options(moved_place, IncludingDowncast(true))
                     .unwrap_or_else(|| "_".to_owned()),
             );
-            err.span_label(span, format!("use of possibly uninitialized {}", item_msg));
+            err.span_label(span, format!("use of possibly-uninitialized {}", item_msg));
 
             use_spans.var_span_label(
                 &mut err,
@@ -244,7 +244,7 @@
                 }
                 let span = if let Place {
                     base: PlaceBase::Local(local),
-                    projection: None,
+                    projection: box [],
                 } = place {
                     let decl = &self.body.local_decls[*local];
                     Some(decl.source_info.span)
@@ -614,17 +614,18 @@
                     projection,
                 } = first_borrowed_place;
 
-                let mut current = projection;
+                let mut cursor = &**projection;
+                while let [proj_base @ .., elem] = cursor {
+                    cursor = proj_base;
 
-                while let Some(box Projection { base: base_proj, elem }) = current {
                     match elem {
-                        ProjectionElem::Field(field, _) if union_ty(base, base_proj).is_some() => {
+                        ProjectionElem::Field(field, _) if union_ty(base, proj_base).is_some() => {
                             return Some((PlaceRef {
                                 base: base,
-                                projection: base_proj,
+                                projection: proj_base,
                             }, field));
                         },
-                        _ => current = base_proj,
+                        _ => {},
                     }
                 }
                 None
@@ -637,9 +638,10 @@
                     projection,
                 } = second_borrowed_place;
 
-                let mut current = projection;
+                let mut cursor = &**projection;
+                while let [proj_base @ .., elem] = cursor {
+                    cursor = proj_base;
 
-                while let Some(box Projection { base: proj_base, elem }) = current {
                     if let ProjectionElem::Field(field, _) = elem {
                         if let Some(union_ty) = union_ty(base, proj_base) {
                             if field != target_field
@@ -660,8 +662,6 @@
                             }
                         }
                     }
-
-                    current = proj_base;
                 }
                 None
             })
@@ -707,7 +707,7 @@
         let borrow_spans = self.retrieve_borrow_spans(borrow);
         let borrow_span = borrow_spans.var_or_use();
 
-        assert!(root_place.projection.is_none());
+        assert!(root_place.projection.is_empty());
         let proper_span = match root_place.base {
             PlaceBase::Local(local) => self.body.local_decls[*local].source_info.span,
             _ => drop_span,
@@ -716,7 +716,7 @@
         if self.access_place_error_reported
             .contains(&(Place {
                 base: root_place.base.clone(),
-                projection: root_place.projection.clone(),
+                projection: root_place.projection.to_vec().into_boxed_slice(),
             }, borrow_span))
         {
             debug!(
@@ -729,7 +729,7 @@
         self.access_place_error_reported
             .insert((Place {
                 base: root_place.base.clone(),
-                projection: root_place.projection.clone(),
+                projection: root_place.projection.to_vec().into_boxed_slice(),
             }, borrow_span));
 
         if let StorageDeadOrDrop::Destructor(dropped_ty) =
@@ -1107,7 +1107,7 @@
             let local_kind = match borrow.borrowed_place {
                 Place {
                     base: PlaceBase::Local(local),
-                    projection: None,
+                    projection: box [],
                 } => {
                     match self.body.local_kind(local) {
                         LocalKind::ReturnPointer
@@ -1136,7 +1136,7 @@
                 .unwrap();
             let local = if let PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: [],
             } = root_place {
                 local
             } else {
@@ -1446,7 +1446,7 @@
     ) {
         let (from_arg, local_decl) = if let Place {
             base: PlaceBase::Local(local),
-            projection: None,
+            projection: box [],
         } = *err_place {
             if let LocalKind::Arg = self.body.local_kind(local) {
                 (true, Some(&self.body.local_decls[local]))
@@ -1519,20 +1519,21 @@
     fn classify_drop_access_kind(&self, place: PlaceRef<'cx, 'tcx>) -> StorageDeadOrDrop<'tcx> {
         let tcx = self.infcx.tcx;
         match place.projection {
-            None => {
+            [] => {
                 StorageDeadOrDrop::LocalStorageDead
             }
-            Some(box Projection { ref base, ref elem }) => {
+            [proj_base @ .., elem] => {
+                // FIXME(spastorino) make this iterate
                 let base_access = self.classify_drop_access_kind(PlaceRef {
                     base: place.base,
-                    projection: base,
+                    projection: proj_base,
                 });
                 match elem {
                     ProjectionElem::Deref => match base_access {
                         StorageDeadOrDrop::LocalStorageDead
                         | StorageDeadOrDrop::BoxedStorageDead => {
                             assert!(
-                                Place::ty_from(&place.base, base, self.body, tcx).ty.is_box(),
+                                Place::ty_from(&place.base, proj_base, self.body, tcx).ty.is_box(),
                                 "Drop of value behind a reference or raw pointer"
                             );
                             StorageDeadOrDrop::BoxedStorageDead
@@ -1540,7 +1541,7 @@
                         StorageDeadOrDrop::Destructor(_) => base_access,
                     },
                     ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
-                        let base_ty = Place::ty_from(&place.base, base, self.body, tcx).ty;
+                        let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty;
                         match base_ty.sty {
                             ty::Adt(def, _) if def.has_dtor(tcx) => {
                                 // Report the outermost adt with a destructor
@@ -1598,7 +1599,7 @@
             "annotate_argument_and_return_for_borrow: location={:?}",
             location
         );
-        if let Some(&Statement { kind: StatementKind::Assign(ref reservation, _), ..})
+        if let Some(&Statement { kind: StatementKind::Assign(box(ref reservation, _)), ..})
              = &self.body[location.block].statements.get(location.statement_index)
         {
             debug!(
@@ -1609,7 +1610,7 @@
             let mut target = *match reservation {
                 Place {
                     base: PlaceBase::Local(local),
-                    projection: None,
+                    projection: box [],
                 } if self.body.local_kind(*local) == LocalKind::Temp => local,
                 _ => return None,
             };
@@ -1623,11 +1624,13 @@
                     target, stmt
                 );
                 if let StatementKind::Assign(
-                    Place {
-                        base: PlaceBase::Local(assigned_to),
-                        projection: None,
-                    },
-                    box rvalue
+                    box(
+                        Place {
+                            base: PlaceBase::Local(assigned_to),
+                            projection: box [],
+                        },
+                        rvalue
+                    )
                 ) = &stmt.kind {
                     debug!(
                         "annotate_argument_and_return_for_borrow: assigned_to={:?} \
@@ -1753,7 +1756,7 @@
             if let TerminatorKind::Call {
                 destination: Some((Place {
                     base: PlaceBase::Local(assigned_to),
-                    projection: None,
+                    projection: box [],
                 }, _)),
                 args,
                 ..
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 251d4b7..5bccd28 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -41,7 +41,7 @@
         let mut target = place.local_or_deref_local();
         for stmt in &self.body[location.block].statements[location.statement_index..] {
             debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target);
-            if let StatementKind::Assign(into, box Rvalue::Use(from)) = &stmt.kind {
+            if let StatementKind::Assign(box(into, Rvalue::Use(from))) = &stmt.kind {
                 debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
                 match from {
                     Operand::Copy(ref place) |
@@ -152,7 +152,7 @@
         match place {
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: [],
             } => {
                 self.append_local_to_string(*local, buf)?;
             }
@@ -162,7 +162,7 @@
                         kind: StaticKind::Promoted(..),
                         ..
                     }),
-                projection: None,
+                projection: [],
             } => {
                 buf.push_str("promoted");
             }
@@ -173,15 +173,15 @@
                         def_id,
                         ..
                     }),
-                projection: None,
+                projection: [],
             } => {
                 buf.push_str(&self.infcx.tcx.item_name(*def_id).to_string());
             }
             PlaceRef {
                 base,
-                projection: Some(ref proj),
+                projection: [proj_base @ .., elem],
             } => {
-                match proj.elem {
+                match elem {
                     ProjectionElem::Deref => {
                         let upvar_field_projection =
                             self.is_upvar_field_projection(place);
@@ -199,20 +199,20 @@
                                 self.append_place_to_string(
                                     PlaceRef {
                                         base,
-                                        projection: &proj.base,
+                                        projection: proj_base,
                                     },
                                     buf,
                                     autoderef,
                                     &including_downcast,
                                 )?;
                             } else {
-                                match (&proj.base, base) {
-                                    (None, PlaceBase::Local(local)) => {
+                                match (proj_base, base) {
+                                    ([], PlaceBase::Local(local)) => {
                                         if self.body.local_decls[*local].is_ref_for_guard() {
                                             self.append_place_to_string(
                                                 PlaceRef {
                                                     base,
-                                                    projection: &proj.base,
+                                                    projection: proj_base,
                                                 },
                                                 buf,
                                                 autoderef,
@@ -224,7 +224,7 @@
                                             self.append_place_to_string(
                                                 PlaceRef {
                                                     base,
-                                                    projection: &proj.base,
+                                                    projection: proj_base,
                                                 },
                                                 buf,
                                                 autoderef,
@@ -238,7 +238,7 @@
                                         self.append_place_to_string(
                                             PlaceRef {
                                                 base,
-                                                projection: &proj.base,
+                                                projection: proj_base,
                                             },
                                             buf,
                                             autoderef,
@@ -253,7 +253,7 @@
                         self.append_place_to_string(
                             PlaceRef {
                                 base,
-                                projection: &proj.base,
+                                projection: proj_base,
                             },
                             buf,
                             autoderef,
@@ -275,12 +275,12 @@
                         } else {
                             let field_name = self.describe_field(PlaceRef {
                                 base,
-                                projection: &proj.base,
-                            }, field);
+                                projection: proj_base,
+                            }, *field);
                             self.append_place_to_string(
                                 PlaceRef {
                                     base,
-                                    projection: &proj.base,
+                                    projection: proj_base,
                                 },
                                 buf,
                                 autoderef,
@@ -295,14 +295,14 @@
                         self.append_place_to_string(
                             PlaceRef {
                                 base,
-                                projection: &proj.base,
+                                projection: proj_base,
                             },
                             buf,
                             autoderef,
                             &including_downcast,
                         )?;
                         buf.push_str("[");
-                        if self.append_local_to_string(index, buf).is_err() {
+                        if self.append_local_to_string(*index, buf).is_err() {
                             buf.push_str("_");
                         }
                         buf.push_str("]");
@@ -315,7 +315,7 @@
                         self.append_place_to_string(
                             PlaceRef {
                                 base,
-                                projection: &proj.base,
+                                projection: proj_base,
                             },
                             buf,
                             autoderef,
@@ -336,7 +336,7 @@
         let local = &self.body.local_decls[local_index];
         match local.name {
             Some(name) if !local.from_compiler_desugaring() => {
-                buf.push_str(name.as_str().get());
+                buf.push_str(&name.as_str());
                 Ok(())
             }
             _ => Err(()),
@@ -349,28 +349,30 @@
         match place {
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: [],
             } => {
                 let local = &self.body.local_decls[*local];
                 self.describe_field_from_ty(&local.ty, field, None)
             }
             PlaceRef {
                 base: PlaceBase::Static(static_),
-                projection: None,
+                projection: [],
             } =>
                 self.describe_field_from_ty(&static_.ty, field, None),
             PlaceRef {
                 base,
-                projection: Some(proj),
-            } => match proj.elem {
-                ProjectionElem::Deref => self.describe_field(PlaceRef {
-                    base,
-                    projection: &proj.base,
-                }, field),
+                projection: [proj_base @ .., elem],
+            } => match elem {
+                ProjectionElem::Deref => {
+                    self.describe_field(PlaceRef {
+                        base,
+                        projection: proj_base,
+                    }, field)
+                }
                 ProjectionElem::Downcast(_, variant_index) => {
                     let base_ty =
                         Place::ty_from(place.base, place.projection, self.body, self.infcx.tcx).ty;
-                    self.describe_field_from_ty(&base_ty, field, Some(variant_index))
+                    self.describe_field_from_ty(&base_ty, field, Some(*variant_index))
                 }
                 ProjectionElem::Field(_, field_type) => {
                     self.describe_field_from_ty(&field_type, field, None)
@@ -380,7 +382,7 @@
                 | ProjectionElem::Subslice { .. } => {
                     self.describe_field(PlaceRef {
                         base,
-                        projection: &proj.base,
+                        projection: proj_base,
                     }, field)
                 }
             },
@@ -445,7 +447,7 @@
                 def_id,
                 ..
             }),
-            projection: None,
+            projection: [],
         } = place_ref {
             let attrs = self.infcx.tcx.get_attrs(*def_id);
             let is_thread_local = attrs.iter().any(|attr| attr.check_name(sym::thread_local));
@@ -790,8 +792,7 @@
 
         debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
         if let  StatementKind::Assign(
-            _,
-            box Rvalue::Aggregate(ref kind, ref places)
+            box(_, Rvalue::Aggregate(ref kind, ref places))
         ) = stmt.kind {
             let (def_id, is_generator) = match kind {
                 box AggregateKind::Closure(def_id, _) => (def_id, false),
@@ -828,10 +829,10 @@
             .get(location.statement_index)
         {
             Some(&Statement {
-                kind: StatementKind::Assign(Place {
+                kind: StatementKind::Assign(box(Place {
                     base: PlaceBase::Local(local),
-                    projection: None,
-                }, _),
+                    projection: box [],
+                }, _)),
                 ..
             }) => local,
             _ => return OtherUse(use_span),
@@ -844,7 +845,7 @@
 
         for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
             if let StatementKind::Assign(
-                _, box Rvalue::Aggregate(ref kind, ref places)
+                box(_, Rvalue::Aggregate(ref kind, ref places))
             ) = stmt.kind {
                 let (def_id, is_generator) = match kind {
                     box AggregateKind::Closure(def_id, _) => (def_id, false),
diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs
index bb217a1..4400e0c 100644
--- a/src/librustc_mir/borrow_check/flows.rs
+++ b/src/librustc_mir/borrow_check/flows.rs
@@ -12,7 +12,7 @@
 use polonius_engine::Output;
 
 use crate::dataflow::indexes::BorrowIndex;
-use crate::dataflow::move_paths::HasMoveData;
+use crate::dataflow::move_paths::{HasMoveData, MovePathIndex};
 use crate::dataflow::Borrows;
 use crate::dataflow::EverInitializedPlaces;
 use crate::dataflow::MaybeUninitializedPlaces;
@@ -21,7 +21,7 @@
 use std::fmt;
 use std::rc::Rc;
 
-crate type PoloniusOutput = Output<RegionVid, BorrowIndex, LocationIndex, Local>;
+crate type PoloniusOutput = Output<RegionVid, BorrowIndex, LocationIndex, Local, MovePathIndex>;
 
 // (forced to be `pub` due to its use as an associated type below.)
 crate struct Flows<'b, 'tcx> {
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 8ded539..1d35762 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -10,10 +10,10 @@
 use rustc::middle::borrowck::SignalledError;
 use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc::mir::{
-    ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, PlaceRef,
-    Static, StaticKind
+    ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, PlaceElem,
+    PlaceRef, Static, StaticKind
 };
-use rustc::mir::{Field, Projection, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
+use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
@@ -164,8 +164,8 @@
         };
 
     let mdpe = MoveDataParamEnv {
-        move_data: move_data,
-        param_env: param_env,
+        move_data,
+        param_env,
     };
 
     let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
@@ -259,7 +259,10 @@
         move_error_reported: BTreeMap::new(),
         uninitialized_error_reported: Default::default(),
         errors_buffer,
-        disable_error_downgrading: false,
+        // Only downgrade errors on Rust 2015 and refuse to do so on Rust 2018.
+        // FIXME(Centril): In Rust 1.40.0, refuse doing so on 2015 as well and
+        // proceed to throwing out the migration infrastructure.
+        disable_error_downgrading: body.span.rust_2018(),
         nonlexical_regioncx: regioncx,
         used_mut: Default::default(),
         used_mut_upvars: SmallVec::new(),
@@ -543,7 +546,7 @@
         self.check_activations(location, span, flow_state);
 
         match stmt.kind {
-            StatementKind::Assign(ref lhs, ref rhs) => {
+            StatementKind::Assign(box(ref lhs, ref rhs)) => {
                 self.consume_rvalue(
                     location,
                     (rhs, span),
@@ -558,7 +561,7 @@
                     flow_state,
                 );
             }
-            StatementKind::FakeRead(_, ref place) => {
+            StatementKind::FakeRead(_, box ref place) => {
                 // Read for match doesn't access any memory and is used to
                 // assert that a place is safe and live. So we don't have to
                 // do any checks here.
@@ -902,7 +905,7 @@
 
 struct RootPlace<'d, 'tcx> {
     place_base: &'d PlaceBase<'tcx>,
-    place_projection: &'d Option<Box<Projection<'tcx>>>,
+    place_projection: &'d [PlaceElem<'tcx>],
     is_local_mutation_allowed: LocalMutationIsAllowed,
 }
 
@@ -1188,7 +1191,7 @@
         // before (at this point in the flow).
         if let Place {
             base: PlaceBase::Local(local),
-            projection: None,
+            projection: box [],
         } = place_span.0 {
             if let Mutability::Not = self.body.local_decls[*local].mutability {
                 // check for reassignments to immutable local variables
@@ -1328,7 +1331,7 @@
 
     fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) {
         let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| {
-            if place.projection.is_some() {
+            if !place.projection.is_empty() {
                 if let Some(field) = this.is_upvar_field_projection(place.as_ref()) {
                     this.used_mut_upvars.push(field);
                 }
@@ -1343,11 +1346,11 @@
         match *operand {
             Operand::Move(Place {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: box [],
             }) |
             Operand::Copy(Place {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: box [],
             }) if self.body.local_decls[local].is_user_variable.is_none() => {
                 if self.body.local_decls[local].ty.is_mutable_ptr() {
                     // The variable will be marked as mutable by the borrow.
@@ -1384,7 +1387,7 @@
                 let stmt = &bbd.statements[loc.statement_index];
                 debug!("temporary assigned in: stmt={:?}", stmt);
 
-                if let StatementKind::Assign(_, box Rvalue::Ref(_, _, ref source)) = stmt.kind {
+                if let StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref source))) = stmt.kind {
                     propagate_closure_used_mut_place(self, source);
                 } else {
                     bug!("closures should only capture user variables \
@@ -1465,7 +1468,7 @@
         //
         // FIXME: allow thread-locals to borrow other thread locals?
 
-        assert!(root_place.projection.is_none());
+        assert!(root_place.projection.is_empty());
         let (might_be_alive, will_be_dropped) = match root_place.base {
             PlaceBase::Static(box Static {
                 kind: StaticKind::Promoted(..),
@@ -1753,13 +1756,13 @@
         flow_state: &Flows<'cx, 'tcx>,
     ) {
         debug!("check_if_assigned_path_is_moved place: {:?}", place);
-        // recur down place; dispatch to external checks when necessary
-        let mut place_projection = &place.projection;
 
         // None case => assigning to `x` does not require `x` be initialized.
-        while let Some(proj) = place_projection {
-            let Projection { ref base, ref elem } = **proj;
-            match *elem {
+        let mut cursor = &*place.projection;
+        while let [proj_base @ .., elem] = cursor {
+            cursor = proj_base;
+
+            match elem {
                 ProjectionElem::Index(_/*operand*/) |
                 ProjectionElem::ConstantIndex { .. } |
                 // assigning to P[i] requires P to be valid.
@@ -1775,7 +1778,7 @@
                         location, InitializationRequiringAction::Use,
                         (PlaceRef {
                             base: &place.base,
-                            projection: base,
+                            projection: proj_base,
                         }, span), flow_state);
                     // (base initialized; no need to
                     // recur further)
@@ -1792,14 +1795,14 @@
                     // assigning to `P.f` requires `P` itself
                     // be already initialized
                     let tcx = self.infcx.tcx;
-                    let base_ty = Place::ty_from(&place.base, base, self.body, tcx).ty;
+                    let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty;
                     match base_ty.sty {
                         ty::Adt(def, _) if def.has_dtor(tcx) => {
                             self.check_if_path_or_subpath_is_moved(
                                 location, InitializationRequiringAction::Assignment,
                                 (PlaceRef {
                                     base: &place.base,
-                                    projection: base,
+                                    projection: proj_base,
                                 }, span), flow_state);
 
                             // (base initialized; no need to
@@ -1812,7 +1815,7 @@
                         ty::Adt(..) | ty::Tuple(..) => {
                             check_parent_of_field(self, location, PlaceRef {
                                 base: &place.base,
-                                projection: base,
+                                projection: proj_base,
                             }, span, flow_state);
 
                             if let PlaceBase::Local(local) = place.base {
@@ -1832,8 +1835,6 @@
                     }
                 }
             }
-
-            place_projection = base;
         }
 
         fn check_parent_of_field<'cx, 'tcx>(
@@ -2081,7 +2082,7 @@
         match root_place {
             RootPlace {
                 place_base: PlaceBase::Local(local),
-                place_projection: None,
+                place_projection: [],
                 is_local_mutation_allowed,
             } => {
                 // If the local may have been initialized, and it is now currently being
@@ -2100,7 +2101,7 @@
             } => {}
             RootPlace {
                 place_base,
-                place_projection: place_projection @ Some(_),
+                place_projection: place_projection @ [.., _],
                 is_local_mutation_allowed: _,
             } => {
                 if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@@ -2112,7 +2113,7 @@
             }
             RootPlace {
                 place_base: PlaceBase::Static(..),
-                place_projection: None,
+                place_projection: [],
                 is_local_mutation_allowed: _,
             } => {}
         }
@@ -2128,7 +2129,7 @@
         match place {
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: [],
             } => {
                 let local = &self.body.local_decls[*local];
                 match local.mutability {
@@ -2159,7 +2160,7 @@
                     kind: StaticKind::Promoted(..),
                     ..
                 }),
-                projection: None,
+                projection: [],
             } =>
                 Ok(RootPlace {
                     place_base: place.base,
@@ -2172,7 +2173,7 @@
                     def_id,
                     ..
                 }),
-                projection: None,
+                projection: [],
             } => {
                 if !self.infcx.tcx.is_mutable_static(*def_id) {
                     Err(place)
@@ -2186,12 +2187,12 @@
             }
             PlaceRef {
                 base: _,
-                projection: Some(proj),
+                projection: [proj_base @ .., elem],
             } => {
-                match proj.elem {
+                match elem {
                     ProjectionElem::Deref => {
                         let base_ty =
-                            Place::ty_from(place.base, &proj.base, self.body, self.infcx.tcx).ty;
+                            Place::ty_from(place.base, proj_base, self.body, self.infcx.tcx).ty;
 
                         // Check the kind of deref to decide
                         match base_ty.sty {
@@ -2213,7 +2214,7 @@
 
                                         self.is_mutable(PlaceRef {
                                             base: place.base,
-                                            projection: &proj.base,
+                                            projection: proj_base,
                                         }, mode)
                                     }
                                 }
@@ -2237,7 +2238,7 @@
                             _ if base_ty.is_box() => {
                                 self.is_mutable(PlaceRef {
                                     base: place.base,
-                                    projection: &proj.base,
+                                    projection: proj_base,
                                 }, is_local_mutation_allowed)
                             }
                             // Deref should only be for reference, pointers or boxes
@@ -2294,7 +2295,7 @@
                                     // ```
                                     let _ = self.is_mutable(PlaceRef {
                                         base: place.base,
-                                        projection: &proj.base,
+                                        projection: proj_base,
                                     }, is_local_mutation_allowed)?;
                                     Ok(RootPlace {
                                         place_base: place.base,
@@ -2306,7 +2307,7 @@
                         } else {
                             self.is_mutable(PlaceRef {
                                 base: place.base,
-                                projection: &proj.base,
+                                projection: proj_base,
                             }, is_local_mutation_allowed)
                         }
                     }
@@ -2323,21 +2324,15 @@
         let mut place_projection = place_ref.projection;
         let mut by_ref = false;
 
-        if let Some(box Projection {
-            base,
-            elem: ProjectionElem::Deref,
-        }) = place_projection {
-            place_projection = &base;
+        if let [proj_base @ .., ProjectionElem::Deref] = place_projection {
+            place_projection = proj_base;
             by_ref = true;
         }
 
         match place_projection {
-            Some(box Projection {
-                base,
-                elem: ProjectionElem::Field(field, _ty),
-            }) => {
+            [base @ .., ProjectionElem::Field(field, _ty)] => {
                 let tcx = self.infcx.tcx;
-                let base_ty = Place::ty_from(place_ref.base, &base, self.body, tcx).ty;
+                let base_ty = Place::ty_from(place_ref.base, base, self.body, tcx).ty;
 
                 if (base_ty.is_closure() || base_ty.is_generator()) &&
                     (!by_ref || self.upvars[field.index()].by_ref) {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index f10ff71..aa732b0 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -1,5 +1,3 @@
-use core::unicode::property::Pattern_White_Space;
-
 use rustc::mir::*;
 use rustc::ty;
 use rustc_errors::{DiagnosticBuilder,Applicability};
@@ -91,11 +89,13 @@
                 // If that ever stops being the case, then the ever initialized
                 // flow could be used.
                 if let Some(StatementKind::Assign(
-                    Place {
-                        base: PlaceBase::Local(local),
-                        projection: None,
-                    },
-                    box Rvalue::Use(Operand::Move(move_from)),
+                    box(
+                        Place {
+                            base: PlaceBase::Local(local),
+                            projection: box [],
+                        },
+                        Rvalue::Use(Operand::Move(move_from))
+                    )
                 )) = self.body.basic_blocks()[location.block]
                     .statements
                     .get(location.statement_index)
@@ -276,16 +276,12 @@
         place: &Place<'tcx>,
         span: Span
     ) -> DiagnosticBuilder<'a> {
-        let description = if place.projection.is_none() {
+        let description = if place.projection.is_empty() {
             format!("static item `{}`", self.describe_place(place.as_ref()).unwrap())
         } else {
-            let mut base_static = &place.projection;
-            while let Some(box Projection { base: Some(ref proj), .. }) = base_static {
-                base_static = &proj.base;
-            }
             let base_static = PlaceRef {
                 base: &place.base,
-                projection: base_static,
+                projection: &place.projection[..1],
             };
 
             format!(
@@ -311,17 +307,19 @@
         let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All)
             .find_map(|p| self.is_upvar_field_projection(p));
 
-        let deref_base = match deref_target_place.projection {
-            Some(box Projection { ref base, elem: ProjectionElem::Deref }) => PlaceRef {
-                base: &deref_target_place.base,
-                projection: base,
-            },
+        let deref_base = match &deref_target_place.projection {
+            box [proj_base @ .., ProjectionElem::Deref] => {
+                PlaceRef {
+                    base: &deref_target_place.base,
+                    projection: proj_base,
+                }
+            }
             _ => bug!("deref_target_place is not a deref projection"),
         };
 
         if let PlaceRef {
             base: PlaceBase::Local(local),
-            projection: None,
+            projection: [],
         } = deref_base {
             let decl = &self.body.local_decls[*local];
             if decl.is_ref_for_guard() {
@@ -526,7 +524,7 @@
                         let suggestion;
                         let to_remove;
                         if pat_snippet.starts_with("mut")
-                            && pat_snippet["mut".len()..].starts_with(Pattern_White_Space)
+                            && pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
                         {
                             suggestion = pat_snippet["mut".len()..].trim_start();
                             to_remove = "&mut";
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 5a55349..14b76d9 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -1,9 +1,8 @@
-use core::unicode::property::Pattern_White_Space;
 use rustc::hir;
 use rustc::hir::Node;
 use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Body};
 use rustc::mir::{
-    Mutability, Place, PlaceRef, PlaceBase, Projection, ProjectionElem, Static, StaticKind
+    Mutability, Place, PlaceRef, PlaceBase, ProjectionElem, Static, StaticKind
 };
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
@@ -48,12 +47,12 @@
         match the_place_err {
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: [],
             } => {
                 item_msg = format!("`{}`", access_place_desc.unwrap());
                 if let Place {
                     base: PlaceBase::Local(_),
-                    projection: None,
+                    projection: box [],
                 } = access_place {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
@@ -66,14 +65,10 @@
 
             PlaceRef {
                 base: _,
-                projection:
-                    Some(box Projection {
-                        base,
-                        elem: ProjectionElem::Field(upvar_index, _),
-                    }),
+                projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             } => {
                 debug_assert!(is_closure_or_generator(
-                    Place::ty_from(&the_place_err.base, &base, self.body, self.infcx.tcx).ty
+                    Place::ty_from(&the_place_err.base, proj_base, self.body, self.infcx.tcx).ty
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
@@ -87,14 +82,10 @@
 
             PlaceRef {
                 base: _,
-                projection:
-                    Some(box Projection {
-                        base,
-                        elem: ProjectionElem::Deref,
-                    }),
+                projection: [proj_base @ .., ProjectionElem::Deref],
             } => {
                 if the_place_err.base == &PlaceBase::Local(Local::new(1)) &&
-                    base.is_none() &&
+                    proj_base.is_empty() &&
                     !self.upvars.is_empty() {
                     item_msg = format!("`{}`", access_place_desc.unwrap());
                     debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr());
@@ -115,7 +106,7 @@
                             ", as `Fn` closures cannot mutate their captured variables".to_string()
                         }
                 } else if {
-                    if let (PlaceBase::Local(local), None) = (&the_place_err.base, base) {
+                    if let (PlaceBase::Local(local), []) = (&the_place_err.base, proj_base) {
                         self.body.local_decls[*local].is_ref_for_guard()
                     } else {
                         false
@@ -126,7 +117,7 @@
                 } else {
                     let source = self.borrowed_content_source(PlaceRef {
                         base: the_place_err.base,
-                        projection: base,
+                        projection: proj_base,
                     });
                     let pointer_type = source.describe_for_immutable_place();
                     opt_source = Some(source);
@@ -152,7 +143,7 @@
                         kind: StaticKind::Promoted(..),
                         ..
                     }),
-                projection: None,
+                projection: [],
             } => unreachable!(),
 
             PlaceRef {
@@ -162,11 +153,11 @@
                         def_id,
                         ..
                     }),
-                projection: None,
+                projection: [],
             } => {
                 if let Place {
                     base: PlaceBase::Static(_),
-                    projection: None,
+                    projection: box [],
                 } = access_place {
                     item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
                     reason = String::new();
@@ -179,33 +170,19 @@
 
             PlaceRef {
                 base: _,
-                projection:
-                    Some(box Projection {
-                        base: _,
-                        elem: ProjectionElem::Index(_),
-                    }),
+                projection: [.., ProjectionElem::Index(_)],
             }
             | PlaceRef {
                 base: _,
-                projection:
-                    Some(box Projection {
-                        base: _,
-                        elem: ProjectionElem::ConstantIndex { .. },
-                    }),
+                projection: [.., ProjectionElem::ConstantIndex { .. }],
             }
             | PlaceRef {
                 base: _,
-                projection: Some(box Projection {
-                    base: _,
-                    elem: ProjectionElem::Subslice { .. },
-                }),
+                projection: [.., ProjectionElem::Subslice { .. }],
             }
             | PlaceRef {
                 base: _,
-                projection: Some(box Projection {
-                    base: _,
-                    elem: ProjectionElem::Downcast(..),
-                }),
+                projection: [.., ProjectionElem::Downcast(..)],
             } => bug!("Unexpected immutable place."),
         }
 
@@ -263,22 +240,17 @@
             // after the field access).
             PlaceRef {
                 base,
-                projection: Some(box Projection {
-                    base: Some(box Projection {
-                        base: Some(box Projection {
-                            base: base_proj,
-                            elem: ProjectionElem::Deref,
-                        }),
-                        elem: ProjectionElem::Field(field, _),
-                    }),
-                    elem: ProjectionElem::Deref,
-                }),
+                projection: [proj_base @ ..,
+                             ProjectionElem::Deref,
+                             ProjectionElem::Field(field, _),
+                             ProjectionElem::Deref,
+                ],
             } => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
 
                 if let Some((span, message)) = annotate_struct_field(
                     self.infcx.tcx,
-                    Place::ty_from(&base, &base_proj, self.body, self.infcx.tcx).ty,
+                    Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty,
                     field,
                 ) {
                     err.span_suggestion(
@@ -293,7 +265,7 @@
             // Suggest removing a `&mut` from the use of a mutable reference.
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: [],
             } if {
                 self.body.local_decls.get(*local).map(|local_decl| {
                     if let ClearCrossCrate::Set(
@@ -329,7 +301,7 @@
             // variable) mutations...
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: [],
             } if self.body.local_decls[*local].can_be_made_mutable() => {
                 // ... but it doesn't make sense to suggest it on
                 // variables that are `ref x`, `ref mut x`, `&self`,
@@ -350,13 +322,10 @@
             // Also suggest adding mut for upvars
             PlaceRef {
                 base,
-                projection: Some(box Projection {
-                    base: proj_base,
-                    elem: ProjectionElem::Field(upvar_index, _),
-                }),
+                projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             } => {
                 debug_assert!(is_closure_or_generator(
-                    Place::ty_from(&base, &proj_base, self.body, self.infcx.tcx).ty
+                    Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty
                 ));
 
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
@@ -386,7 +355,7 @@
             // a local variable, then just suggest the user remove it.
             PlaceRef {
                 base: PlaceBase::Local(_),
-                projection: None,
+                projection: [],
             } if {
                     if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
                         snippet.starts_with("&mut ")
@@ -401,10 +370,7 @@
 
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: Some(box Projection {
-                    base: None,
-                    elem: ProjectionElem::Deref,
-                }),
+                projection: [ProjectionElem::Deref],
             } if {
                 if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
                     self.body.local_decls[*local].is_user_variable
@@ -428,10 +394,7 @@
             // arbitrary base for the projection?
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: Some(box Projection {
-                    base: None,
-                    elem: ProjectionElem::Deref,
-                }),
+                projection: [ProjectionElem::Deref],
             } if self.body.local_decls[*local].is_user_variable.is_some() =>
             {
                 let local_decl = &self.body.local_decls[*local];
@@ -511,10 +474,7 @@
 
             PlaceRef {
                 base,
-                projection: Some(box Projection {
-                    base: None,
-                    elem: ProjectionElem::Deref,
-                }),
+                projection: [ProjectionElem::Deref],
             // FIXME document what is this 1 magic number about
             } if *base == PlaceBase::Local(Local::new(1)) &&
                   !self.upvars.is_empty() =>
@@ -528,10 +488,7 @@
 
             PlaceRef {
                 base: _,
-                projection: Some(box Projection {
-                    base: _,
-                    elem: ProjectionElem::Deref,
-                }),
+                projection: [.., ProjectionElem::Deref],
             } => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
 
@@ -715,7 +672,7 @@
 fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option<String> {
     let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).ok()?;
     if hi_src.starts_with("ref")
-        && hi_src["ref".len()..].starts_with(Pattern_White_Space)
+        && hi_src["ref".len()..].starts_with(rustc_lexer::is_whitespace)
     {
         let replacement = format!("ref mut{}", &hi_src["ref".len()..]);
         Some(replacement)
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index 5c23091..1e5f613 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -8,9 +8,8 @@
 use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
 use rustc::mir::{
-    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, Projection,
-    ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind,
-    UserTypeProjection,
+    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, ProjectionElem, Rvalue,
+    SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
 };
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty};
@@ -229,14 +228,11 @@
             match place {
                 Place {
                     base: PlaceBase::Local(local),
-                    projection: None,
+                    projection: box [],
                 } |
                 Place {
                     base: PlaceBase::Local(local),
-                    projection: Some(box Projection {
-                        base: None,
-                        elem: ProjectionElem::Deref,
-                    }),
+                    projection: box [ProjectionElem::Deref],
                 } => {
                     debug!(
                         "Recording `killed` facts for borrows of local={:?} at location={:?}",
@@ -261,7 +257,7 @@
 
                 Place {
                     base: PlaceBase::Local(local),
-                    projection: Some(_),
+                    projection: box [.., _],
                 } => {
                     // Kill conflicting borrows of the innermost local.
                     debug!(
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index aba3ef1..eae2f83 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -274,7 +274,7 @@
                     if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
                         if let Place {
                             base: PlaceBase::Local(borrowed_local),
-                            projection: None,
+                            projection: box [],
                         } = place {
                              if body.local_decls[*borrowed_local].name.is_some()
                                 && local != *borrowed_local
@@ -495,11 +495,11 @@
                             Operand::Constant(c) => c.span,
                             Operand::Copy(Place {
                                 base: PlaceBase::Local(l),
-                                projection: None,
+                                projection: box [],
                             }) |
                             Operand::Move(Place {
                                 base: PlaceBase::Local(l),
-                                projection: None,
+                                projection: box [],
                             }) => {
                                 let local_decl = &self.body.local_decls[*l];
                                 if local_decl.name.is_none() {
@@ -541,10 +541,10 @@
         // it which simplifies the termination logic.
         let mut queue = vec![location];
         let mut target = if let Some(&Statement {
-            kind: StatementKind::Assign(Place {
+            kind: StatementKind::Assign(box(Place {
                 base: PlaceBase::Local(local),
-                projection: None,
-            }, _),
+                projection: box [],
+            }, _)),
             ..
         }) = stmt
         {
@@ -567,7 +567,7 @@
                 debug!("was_captured_by_trait_object: stmt={:?}", stmt);
 
                 // The only kind of statement that we care about is assignments...
-                if let StatementKind::Assign(place, box rvalue) = &stmt.kind {
+                if let StatementKind::Assign(box(place, rvalue)) = &stmt.kind {
                     let into = match place.local_or_deref_local() {
                         Some(into) => into,
                         None => {
@@ -583,11 +583,11 @@
                         Rvalue::Use(operand) => match operand {
                             Operand::Copy(Place {
                                 base: PlaceBase::Local(from),
-                                projection: None,
+                                projection: box [],
                             })
                             | Operand::Move(Place {
                                 base: PlaceBase::Local(from),
-                                projection: None,
+                                projection: box [],
                             })
                                 if *from == target =>
                             {
@@ -602,11 +602,11 @@
                         ) => match operand {
                             Operand::Copy(Place {
                                 base: PlaceBase::Local(from),
-                                projection: None,
+                                projection: box [],
                             })
                             | Operand::Move(Place {
                                 base: PlaceBase::Local(from),
-                                projection: None,
+                                projection: box [],
                             })
                                 if *from == target =>
                             {
@@ -639,7 +639,7 @@
                 if let TerminatorKind::Call {
                     destination: Some((Place {
                         base: PlaceBase::Local(dest),
-                        projection: None,
+                        projection: box [],
                     }, block)),
                     args,
                     ..
@@ -653,7 +653,7 @@
                     let found_target = args.iter().any(|arg| {
                         if let Operand::Move(Place {
                             base: PlaceBase::Local(potential),
-                            projection: None,
+                            projection: box [],
                         }) = arg {
                             *potential == target
                         } else {
diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs
index 05451cd..f0beb4d 100644
--- a/src/librustc_mir/borrow_check/nll/facts.rs
+++ b/src/librustc_mir/borrow_check/nll/facts.rs
@@ -1,5 +1,5 @@
 use crate::borrow_check::location::{LocationIndex, LocationTable};
-use crate::dataflow::indexes::BorrowIndex;
+use crate::dataflow::indexes::{BorrowIndex, MovePathIndex};
 use polonius_engine::AllFacts as PoloniusAllFacts;
 use polonius_engine::Atom;
 use rustc::mir::Local;
@@ -11,7 +11,7 @@
 use std::io::Write;
 use std::path::Path;
 
-crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex, Local>;
+crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex, Local, MovePathIndex>;
 
 crate trait AllFactsExt {
     /// Returns `true` if there is a need to gather `AllFacts` given the
@@ -58,14 +58,17 @@
                 cfg_edge,
                 killed,
                 outlives,
-                region_live_at,
                 invalidates,
                 var_used,
                 var_defined,
                 var_drop_used,
                 var_uses_region,
                 var_drops_region,
-                var_initialized_on_exit,
+                child,
+                path_belongs_to_var,
+                initialized_at,
+                moved_out_at,
+                path_accessed_at,
             ])
         }
         Ok(())
@@ -84,6 +87,12 @@
     }
 }
 
+impl Atom for MovePathIndex {
+    fn index(self) -> usize {
+        Idx::index(self)
+    }
+}
+
 struct FactWriter<'w> {
     location_table: &'w LocationTable,
     dir: &'w Path,
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 71106af..1d429e3 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -66,7 +66,7 @@
         self.check_activations(location);
 
         match statement.kind {
-            StatementKind::Assign(ref lhs, ref rhs) => {
+            StatementKind::Assign(box(ref lhs, ref rhs)) => {
                 self.consume_rvalue(
                     location,
                     rhs,
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 11ec154..1ff3228 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -4,14 +4,15 @@
 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::MoveData;
+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;
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
-use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body, Promoted};
+use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements,
+                 Local, Location, Body, LocalKind, BasicBlock, Promoted};
 use rustc::ty::{self, RegionKind, RegionVid};
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::Diagnostic;
@@ -69,6 +70,85 @@
     universal_regions
 }
 
+
+// This function populates an AllFacts instance with base facts related to
+// MovePaths and needed for the move analysis.
+fn populate_polonius_move_facts(
+    all_facts: &mut AllFacts,
+    move_data: &MoveData<'_>,
+    location_table: &LocationTable,
+    body: &Body<'_>) {
+    all_facts
+        .path_belongs_to_var
+        .extend(
+            move_data
+                .rev_lookup
+                .iter_locals_enumerated()
+                .map(|(v, &m)| (m, v)));
+
+    for (child, move_path) in move_data.move_paths.iter_enumerated() {
+        all_facts
+            .child
+            .extend(
+                move_path
+                    .parents(&move_data.move_paths)
+                    .iter()
+                    .map(|&parent| (child, parent)));
+    }
+
+    // initialized_at
+    for init in move_data.inits.iter() {
+
+        match init.location {
+            InitLocation::Statement(location) => {
+                let block_data = &body[location.block];
+                let is_terminator = location.statement_index == block_data.statements.len();
+
+                if is_terminator && init.kind == InitKind::NonPanicPathOnly {
+                    // We are at the terminator of an init that has a panic path,
+                    // and where the init should not happen on panic
+
+                    for &successor in block_data.terminator().successors() {
+                        if body[successor].is_cleanup {
+                            continue;
+                        }
+
+                        // The initialization happened in (or rather, when arriving at)
+                        // the successors, but not in the unwind block.
+                        let first_statement = Location { block: successor, statement_index: 0};
+                        all_facts
+                            .initialized_at
+                            .push((init.path, location_table.start_index(first_statement)));
+                    }
+
+                } else {
+                    // In all other cases, the initialization just happens at the
+                    // midpoint, like any other effect.
+                    all_facts.initialized_at.push((init.path, location_table.mid_index(location)));
+                }
+            },
+            // Arguments are initialized on function entry
+            InitLocation::Argument(local) => {
+                assert!(body.local_kind(local) == LocalKind::Arg);
+                let fn_entry = Location {block: BasicBlock::from_u32(0u32), statement_index: 0 };
+                all_facts.initialized_at.push((init.path, location_table.start_index(fn_entry)));
+
+            }
+        }
+    }
+
+
+    // moved_out_at
+    // deinitialisation is assumed to always happen!
+    all_facts
+        .moved_out_at
+        .extend(
+            move_data
+                .moves
+                .iter()
+                .map(|mo| (mo.path, location_table.mid_index(mo.source))));
+}
+
 /// Computes the (non-lexical) regions from the input MIR.
 ///
 /// This may result in errors being reported.
@@ -87,7 +167,7 @@
     errors_buffer: &mut Vec<Diagnostic>,
 ) -> (
     RegionInferenceContext<'tcx>,
-    Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex, Local>>>,
+    Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex, Local, MovePathIndex>>>,
     Option<ClosureRegionRequirements<'tcx>>,
 ) {
     let mut all_facts = if AllFacts::enabled(infcx.tcx) {
@@ -123,6 +203,7 @@
         all_facts
             .universal_region
             .extend(universal_regions.universal_regions());
+        populate_polonius_move_facts(all_facts, move_data, location_table, body);
     }
 
     // Create the region inference context, taking ownership of the
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index efa1858..26a89b4 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -13,7 +13,7 @@
 use rustc::mir::{ConstraintCategory, Location, Body};
 use rustc::ty::{self, RegionVid};
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_errors::{Diagnostic, DiagnosticBuilder};
+use rustc_errors::DiagnosticBuilder;
 use std::collections::VecDeque;
 use syntax::errors::Applicability;
 use syntax::symbol::kw;
@@ -22,7 +22,7 @@
 mod region_name;
 mod var_name;
 
-crate use self::region_name::{RegionName, RegionNameSource};
+crate use self::region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
 
 impl ConstraintDescription for ConstraintCategory {
     fn description(&self) -> &'static str {
@@ -54,6 +54,39 @@
     NotVisited,
 }
 
+/// 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.
+    #[allow(dead_code)] // FIXME(mark-i-m): used by outlives suggestions
+    region_infcx: &'b RegionInferenceContext<'tcx>,
+
+    /// The inference context used for type checking.
+    infcx: &'b InferCtxt<'a, 'tcx>,
+
+    /// The MIR def we are reporting errors on.
+    mir_def_id: DefId,
+
+    /// The MIR body we are reporting errors on (for convenience).
+    body: &'b Body<'tcx>,
+
+    /// Any upvars for the MIR body we have kept track of during borrow checking.
+    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,
+
+    // Category and span for best blame constraint
+    category: ConstraintCategory,
+    span: Span,
+}
+
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Tries to find the best constraint to blame for the fact that
     /// `R: from_region`, where `R` is some region that meets
@@ -257,16 +290,16 @@
     /// ```
     ///
     /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
-    pub(super) fn report_error(
-        &self,
+    pub(super) fn report_error<'a>(
+        &'a self,
         body: &Body<'tcx>,
         upvars: &[Upvar],
-        infcx: &InferCtxt<'_, 'tcx>,
+        infcx: &'a InferCtxt<'a, 'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
         outlived_fr: RegionVid,
-        errors_buffer: &mut Vec<Diagnostic>,
-    ) {
+        renctx: &mut RegionErrorNamingCtx,
+    ) -> DiagnosticBuilder<'a> {
         debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
         let (category, _, span) = self.best_blame_constraint(body, fr, |r| {
@@ -279,8 +312,7 @@
             let tables = infcx.tcx.typeck_tables_of(mir_def_id);
             let nice = NiceRegionError::new_from_span(infcx, span, o, f, Some(tables));
             if let Some(diag) = nice.try_report_from_nll() {
-                diag.buffer(errors_buffer);
-                return;
+                return diag;
             }
         }
 
@@ -293,45 +325,28 @@
             "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
             fr_is_local, outlived_fr_is_local, category
         );
+
+        let errctx = ErrorReportingCtx {
+            region_infcx: self,
+            infcx,
+            mir_def_id,
+            body,
+            upvars,
+        };
+
+        let errci = ErrorConstraintInfo {
+            fr, outlived_fr, fr_is_local, outlived_fr_is_local, category, span
+        };
+
         match (category, fr_is_local, outlived_fr_is_local) {
             (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
-                self.report_fnmut_error(
-                    body,
-                    upvars,
-                    infcx,
-                    mir_def_id,
-                    fr,
-                    outlived_fr,
-                    span,
-                    errors_buffer,
-                )
+                self.report_fnmut_error(&errctx, &errci, renctx)
             }
             (ConstraintCategory::Assignment, true, false)
-            | (ConstraintCategory::CallArgument, true, false) => self.report_escaping_data_error(
-                body,
-                upvars,
-                infcx,
-                mir_def_id,
-                fr,
-                outlived_fr,
-                category,
-                span,
-                errors_buffer,
-            ),
-            _ => self.report_general_error(
-                body,
-                upvars,
-                infcx,
-                mir_def_id,
-                fr,
-                fr_is_local,
-                outlived_fr,
-                outlived_fr_is_local,
-                category,
-                span,
-                errors_buffer,
-            ),
-        };
+            | (ConstraintCategory::CallArgument, true, false) =>
+                self.report_escaping_data_error(&errctx, &errci, renctx),
+            _ => self.report_general_error(&errctx, &errci, renctx),
+        }
     }
 
     /// We have a constraint `fr1: fr2` that is not satisfied, where
@@ -379,19 +394,19 @@
     /// ```
     fn report_fnmut_error(
         &self,
-        body: &Body<'tcx>,
-        upvars: &[Upvar],
-        infcx: &InferCtxt<'_, 'tcx>,
-        mir_def_id: DefId,
-        _fr: RegionVid,
-        outlived_fr: RegionVid,
-        span: Span,
-        errors_buffer: &mut Vec<Diagnostic>,
-    ) {
-        let mut diag = infcx
+        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        errci: &ErrorConstraintInfo,
+        renctx: &mut RegionErrorNamingCtx,
+    ) -> DiagnosticBuilder<'_> {
+        let ErrorConstraintInfo {
+            outlived_fr, span, ..
+        } = errci;
+
+        let mut diag = errctx
+            .infcx
             .tcx
             .sess
-            .struct_span_err(span, "captured variable cannot escape `FnMut` closure body");
+            .struct_span_err(*span, "captured variable cannot escape `FnMut` closure body");
 
         // We should check if the return type of this closure is in fact a closure - in that
         // case, we can special case the error further.
@@ -403,11 +418,9 @@
             "returns a reference to a captured variable which escapes the closure body"
         };
 
-        diag.span_label(span, message);
+        diag.span_label(*span, message);
 
-        match self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_fr, &mut 1)
-            .unwrap().source
-        {
+        match self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap().source {
             RegionNameSource::NamedEarlyBoundRegion(fr_span)
             | RegionNameSource::NamedFreeRegion(fr_span)
             | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -427,7 +440,7 @@
         );
         diag.note("...therefore, they cannot allow references to captured variables to escape");
 
-        diag.buffer(errors_buffer);
+        diag
     }
 
     /// Reports a error specifically for when data is escaping a closure.
@@ -444,20 +457,22 @@
     /// ```
     fn report_escaping_data_error(
         &self,
-        body: &Body<'tcx>,
-        upvars: &[Upvar],
-        infcx: &InferCtxt<'_, 'tcx>,
-        mir_def_id: DefId,
-        fr: RegionVid,
-        outlived_fr: RegionVid,
-        category: ConstraintCategory,
-        span: Span,
-        errors_buffer: &mut Vec<Diagnostic>,
-    ) {
+        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        errci: &ErrorConstraintInfo,
+        renctx: &mut RegionErrorNamingCtx,
+    ) -> DiagnosticBuilder<'_> {
+        let ErrorReportingCtx {
+            infcx, body, upvars, ..
+        } = errctx;
+
+        let ErrorConstraintInfo {
+            span, category, ..
+        } = errci;
+
         let fr_name_and_span =
-            self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, fr);
+            self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.fr);
         let outlived_fr_name_and_span =
-            self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, outlived_fr);
+            self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.outlived_fr);
 
         let escapes_from = match self.universal_regions.defining_ty {
             DefiningTy::Closure(..) => "closure",
@@ -469,27 +484,23 @@
         // Revert to the normal error in these cases.
         // Assignments aren't "escapes" in function items.
         if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none())
-            || (category == ConstraintCategory::Assignment && escapes_from == "function")
+            || (*category == ConstraintCategory::Assignment && escapes_from == "function")
             || escapes_from == "const"
         {
             return self.report_general_error(
-                body,
-                upvars,
-                infcx,
-                mir_def_id,
-                fr,
-                true,
-                outlived_fr,
-                false,
-                category,
-                span,
-                errors_buffer,
+                errctx,
+                &ErrorConstraintInfo {
+                    fr_is_local: true,
+                    outlived_fr_is_local: false,
+                    .. *errci
+                },
+                renctx,
             );
         }
 
         let mut diag = borrowck_errors::borrowed_data_escapes_closure(
             infcx.tcx,
-            span,
+            *span,
             escapes_from,
         );
 
@@ -513,12 +524,12 @@
             );
 
             diag.span_label(
-                span,
+                *span,
                 format!("`{}` escapes the {} body here", fr_name, escapes_from),
             );
         }
 
-        diag.buffer(errors_buffer);
+        diag
     }
 
     /// Reports a region inference error for the general case with named/synthesized lifetimes to
@@ -538,41 +549,37 @@
     /// ```
     fn report_general_error(
         &self,
-        body: &Body<'tcx>,
-        upvars: &[Upvar],
-        infcx: &InferCtxt<'_, 'tcx>,
-        mir_def_id: DefId,
-        fr: RegionVid,
-        fr_is_local: bool,
-        outlived_fr: RegionVid,
-        outlived_fr_is_local: bool,
-        category: ConstraintCategory,
-        span: Span,
-        errors_buffer: &mut Vec<Diagnostic>,
-    ) {
+        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        errci: &ErrorConstraintInfo,
+        renctx: &mut RegionErrorNamingCtx,
+    ) -> DiagnosticBuilder<'_> {
+        let ErrorReportingCtx {
+            infcx, mir_def_id, ..
+        } = errctx;
+        let ErrorConstraintInfo {
+            fr, fr_is_local, outlived_fr, outlived_fr_is_local, span, category, ..
+        } = errci;
+
         let mut diag = infcx.tcx.sess.struct_span_err(
-            span,
+            *span,
             "lifetime may not live long enough"
         );
 
-        let counter = &mut 1;
-        let fr_name = self.give_region_a_name(
-            infcx, body, upvars, mir_def_id, fr, counter).unwrap();
-        fr_name.highlight_region_name(&mut diag);
-        let outlived_fr_name =
-            self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_fr, counter).unwrap();
-        outlived_fr_name.highlight_region_name(&mut diag);
-
-        let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
+        let mir_def_name = if infcx.tcx.is_closure(*mir_def_id) {
             "closure"
         } else {
             "function"
         };
 
+        let fr_name = self.give_region_a_name(errctx, renctx, *fr).unwrap();
+        fr_name.highlight_region_name(&mut diag);
+        let outlived_fr_name = self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap();
+        outlived_fr_name.highlight_region_name(&mut diag);
+
         match (category, outlived_fr_is_local, fr_is_local) {
             (ConstraintCategory::Return, true, _) => {
                 diag.span_label(
-                    span,
+                    *span,
                     format!(
                         "{} was supposed to return data with lifetime `{}` but it is returning \
                          data with lifetime `{}`",
@@ -582,7 +589,7 @@
             }
             _ => {
                 diag.span_label(
-                    span,
+                    *span,
                     format!(
                         "{}requires that `{}` must outlive `{}`",
                         category.description(),
@@ -593,9 +600,9 @@
             }
         }
 
-        self.add_static_impl_trait_suggestion(infcx, &mut diag, fr, fr_name, outlived_fr);
+        self.add_static_impl_trait_suggestion(infcx, &mut diag, *fr, fr_name, *outlived_fr);
 
-        diag.buffer(errors_buffer);
+        diag
     }
 
     /// Adds a suggestion to errors where a `impl Trait` is returned.
@@ -704,8 +711,14 @@
             borrow_region,
             |r| self.provides_universal_region(r, borrow_region, outlived_region)
         );
-        let outlived_fr_name =
-            self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_region, &mut 1);
+
+        let mut renctx = RegionErrorNamingCtx::new();
+        let errctx = ErrorReportingCtx {
+            infcx, body, upvars, mir_def_id,
+            region_infcx: self,
+        };
+        let outlived_fr_name = self.give_region_a_name(&errctx, &mut renctx, outlived_region);
+
         (category, from_closure, span, outlived_fr_name)
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index 75a3162..6fa9426 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -1,5 +1,9 @@
 use std::fmt::{self, Display};
-use crate::borrow_check::nll::region_infer::RegionInferenceContext;
+
+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;
@@ -13,29 +17,75 @@
 use rustc::ty::print::RegionHighlightMode;
 use rustc_errors::DiagnosticBuilder;
 use syntax::symbol::kw;
-use syntax_pos::Span;
-use syntax_pos::symbol::InternedString;
+use rustc_data_structures::fx::FxHashMap;
+use syntax_pos::{Span, symbol::InternedString};
 
-#[derive(Debug)]
+/// 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)]
 crate struct RegionName {
+    /// The name of the region (interned).
     crate name: InternedString,
+    /// Where the region comes from.
     crate source: RegionNameSource,
 }
 
-#[derive(Debug)]
+/// Denotes the source of a region that is named by a `RegionName`. For example, a free region that
+/// was named by the user would get `NamedFreeRegion` and `'static` lifetime would get `Static`.
+/// This helps to print the right kinds of diagnostics.
+#[derive(Debug, Clone)]
 crate enum RegionNameSource {
+    /// A bound (not free) region that was substituted at the def site (not an HRTB).
     NamedEarlyBoundRegion(Span),
+    /// A free region that the user has a name (`'a`) for.
     NamedFreeRegion(Span),
+    /// The `'static` region.
     Static,
+    /// The free region corresponding to the environment of a closure.
     SynthesizedFreeEnvRegion(Span, String),
+    /// The region name corresponds to a region where the type annotation is completely missing
+    /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference.
     CannotMatchHirTy(Span, String),
+    /// The region name corresponds a reference that was found by traversing the type in the HIR.
     MatchedHirTy(Span),
+    /// A region name from the generics list of a struct/enum/union.
     MatchedAdtAndSegment(Span),
+    /// The region corresponding to a closure upvar.
     AnonRegionFromUpvar(Span, String),
+    /// The region corresponding to the return type of a closure.
     AnonRegionFromOutput(Span, String, String),
     AnonRegionFromYieldTy(Span, String),
 }
 
+/// Records region names that have been assigned before so that we can use the same ones in later
+/// diagnostics.
+#[derive(Debug, Clone)]
+crate struct RegionErrorNamingCtx {
+    /// Record the region names generated for each region in the given
+    /// MIR def so that we can reuse them later in help/error messages.
+    renctx: FxHashMap<RegionVid, RegionName>,
+
+    /// The counter for generating new region names.
+    counter: usize,
+}
+
+impl RegionErrorNamingCtx {
+    crate fn new() -> Self {
+        Self {
+            counter: 1,
+            renctx: FxHashMap::default(),
+        }
+    }
+
+    crate fn get(&self, region: &RegionVid) -> Option<&RegionName> {
+        self.renctx.get(region)
+    }
+
+    crate fn insert(&mut self, region: RegionVid, name: RegionName) {
+        self.renctx.insert(region, name);
+    }
+}
+
 impl RegionName {
     #[allow(dead_code)]
     crate fn was_named(&self) -> bool {
@@ -63,43 +113,40 @@
         self.name
     }
 
-    crate fn highlight_region_name(
-        &self,
-        diag: &mut DiagnosticBuilder<'_>
-    ) {
+    crate fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) {
         match &self.source {
-            RegionNameSource::NamedFreeRegion(span) |
-            RegionNameSource::NamedEarlyBoundRegion(span) => {
-                diag.span_label(
-                    *span,
-                    format!("lifetime `{}` defined here", self),
-                );
-            },
+            RegionNameSource::NamedFreeRegion(span)
+            | RegionNameSource::NamedEarlyBoundRegion(span) => {
+                diag.span_label(*span, format!("lifetime `{}` defined here", self));
+            }
             RegionNameSource::SynthesizedFreeEnvRegion(span, note) => {
                 diag.span_label(
                     *span,
                     format!("lifetime `{}` represents this closure's body", self),
                 );
                 diag.note(&note);
-            },
+            }
             RegionNameSource::CannotMatchHirTy(span, type_name) => {
                 diag.span_label(*span, format!("has type `{}`", type_name));
-            },
+            }
             RegionNameSource::MatchedHirTy(span) => {
                 diag.span_label(
                     *span,
                     format!("let's call the lifetime of this reference `{}`", self),
                 );
-            },
+            }
             RegionNameSource::MatchedAdtAndSegment(span) => {
                 diag.span_label(*span, format!("let's call this `{}`", self));
-            },
+            }
             RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => {
                 diag.span_label(
                     *span,
-                    format!("lifetime `{}` appears in the type of `{}`", self, upvar_name),
+                    format!(
+                        "lifetime `{}` appears in the type of `{}`",
+                        self, upvar_name
+                    ),
                 );
-            },
+            }
             RegionNameSource::AnonRegionFromOutput(span, mir_description, type_name) => {
                 diag.span_label(
                     *span,
@@ -151,39 +198,49 @@
     /// and then return the name `'1` for us to use.
     crate fn give_region_a_name(
         &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        body: &Body<'tcx>,
-        upvars: &[Upvar],
-        mir_def_id: DefId,
+        errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+        renctx: &mut RegionErrorNamingCtx,
         fr: RegionVid,
-        counter: &mut usize,
     ) -> Option<RegionName> {
-        debug!("give_region_a_name(fr={:?}, counter={})", fr, counter);
+        let ErrorReportingCtx {
+            infcx, body, mir_def_id, upvars, ..
+        } = errctx;
+
+        debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter);
 
         assert!(self.universal_regions.is_universal_region(fr));
 
-        let value = self.give_name_from_error_region(infcx.tcx, mir_def_id, fr, counter)
+        if let Some(value) = renctx.get(&fr) {
+            return Some(value.clone());
+        }
+
+        let value = self
+            .give_name_from_error_region(infcx.tcx, *mir_def_id, fr, renctx)
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_arguments(
-                    infcx, body, mir_def_id, fr, counter,
+                    infcx, body, *mir_def_id, fr, renctx,
                 )
             })
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_upvars(
-                    infcx.tcx, upvars, fr, counter,
+                    infcx.tcx, upvars, fr, renctx
                 )
             })
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_output(
-                    infcx, body, mir_def_id, fr, counter,
+                    infcx, body, *mir_def_id, fr, renctx,
                 )
             })
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_yield_ty(
-                    infcx, body, mir_def_id, fr, counter,
+                    infcx, body, *mir_def_id, fr, renctx,
                 )
             });
 
+        if let Some(ref value) = value {
+            renctx.insert(fr, value.clone());
+        }
+
         debug!("give_region_a_name: gave name {:?}", value);
         value
     }
@@ -197,7 +254,7 @@
         tcx: TyCtxt<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let error_region = self.to_error_region(fr)?;
 
@@ -208,7 +265,7 @@
                     let span = self.get_named_span(tcx, error_region, ebr.name);
                     Some(RegionName {
                         name: ebr.name,
-                        source: RegionNameSource::NamedEarlyBoundRegion(span)
+                        source: RegionNameSource::NamedEarlyBoundRegion(span),
                     })
                 } else {
                     None
@@ -227,12 +284,10 @@
                         name,
                         source: RegionNameSource::NamedFreeRegion(span),
                     })
-                },
+                }
 
                 ty::BoundRegion::BrEnv => {
-                    let mir_hir_id = tcx.hir()
-                                        .as_local_hir_id(mir_def_id)
-                                        .expect("non-local mir");
+                    let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
                     let def_ty = self.universal_regions.defining_ty;
 
                     if let DefiningTy::Closure(def_id, substs) = def_ty {
@@ -243,7 +298,7 @@
                         } else {
                             bug!("Closure is not defined by a closure expr");
                         };
-                        let region_name = self.synthesize_region_name(counter);
+                        let region_name = self.synthesize_region_name(renctx);
 
                         let closure_kind_ty = substs.closure_kind_ty(def_id, tcx);
                         let note = match closure_kind_ty.to_opt_closure_kind() {
@@ -265,7 +320,7 @@
                             name: region_name,
                             source: RegionNameSource::SynthesizedFreeEnvRegion(
                                 args_span,
-                                note.to_string()
+                                note.to_string(),
                             ),
                         })
                     } else {
@@ -335,7 +390,7 @@
         body: &Body<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
         let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?;
@@ -349,12 +404,12 @@
             fr,
             arg_ty,
             argument_index,
-            counter,
+            renctx,
         ) {
             return Some(region_name);
         }
 
-        self.give_name_if_we_cannot_match_hir_ty(infcx, body, fr, arg_ty, counter)
+        self.give_name_if_we_cannot_match_hir_ty(infcx, body, fr, arg_ty, renctx)
     }
 
     fn give_name_if_we_can_match_hir_ty_from_argument(
@@ -365,7 +420,7 @@
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         argument_index: usize,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let mir_hir_id = infcx.tcx.hir().as_local_hir_id(mir_def_id)?;
         let fn_decl = infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
@@ -379,7 +434,7 @@
                 body,
                 needle_fr,
                 argument_ty,
-                counter,
+                renctx,
             ),
 
             _ => self.give_name_if_we_can_match_hir_ty(
@@ -387,7 +442,7 @@
                 needle_fr,
                 argument_ty,
                 argument_hir_ty,
-                counter,
+                renctx,
             ),
         }
     }
@@ -409,10 +464,11 @@
         body: &Body<'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
+        let counter = renctx.counter;
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(needle_fr, *counter);
+        highlight.highlighting_region_vid(needle_fr, counter);
         let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)).0;
 
         debug!(
@@ -428,7 +484,7 @@
                 // This counter value will already have been used, so this function will increment
                 // it so the next value will be used next and return the region name that would
                 // have been used.
-                name: self.synthesize_region_name(counter),
+                name: self.synthesize_region_name(renctx),
                 source: RegionNameSource::CannotMatchHirTy(span, type_name),
             })
         } else {
@@ -455,7 +511,7 @@
     /// type. Once we find that, we can use the span of the `hir::Ty`
     /// to add the highlight.
     ///
-    /// This is a somewhat imperfect process, so long the way we also
+    /// This is a somewhat imperfect process, so along the way we also
     /// keep track of the **closest** type we've found. If we fail to
     /// find the exact `&` or `'_` to highlight, then we may fall back
     /// to highlighting that closest type instead.
@@ -465,7 +521,7 @@
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         argument_hir_ty: &hir::Ty,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> =
             &mut vec![(argument_ty, argument_hir_ty)];
@@ -483,7 +539,7 @@
                     hir::TyKind::Rptr(_lifetime, referent_hir_ty),
                 ) => {
                     if region.to_region_vid() == needle_fr {
-                        let region_name = self.synthesize_region_name(counter);
+                        let region_name = self.synthesize_region_name(renctx);
 
                         // Just grab the first character, the `&`.
                         let source_map = tcx.sess.source_map();
@@ -515,7 +571,7 @@
                                 substs,
                                 needle_fr,
                                 last_segment,
-                                counter,
+                                renctx,
                                 search_stack,
                             ) {
                                 return Some(name);
@@ -559,18 +615,19 @@
         substs: SubstsRef<'tcx>,
         needle_fr: RegionVid,
         last_segment: &'hir hir::PathSegment,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>,
     ) -> Option<RegionName> {
         // Did the user give explicit arguments? (e.g., `Foo<..>`)
         let args = last_segment.args.as_ref()?;
-        let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
+        let lifetime =
+            self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
         match lifetime.name {
             hir::LifetimeName::Param(_)
             | hir::LifetimeName::Error
             | hir::LifetimeName::Static
             | hir::LifetimeName::Underscore => {
-                let region_name = self.synthesize_region_name(counter);
+                let region_name = self.synthesize_region_name(renctx);
                 let ampersand_span = lifetime.span;
                 Some(RegionName {
                     name: region_name,
@@ -657,12 +714,12 @@
         tcx: TyCtxt<'tcx>,
         upvars: &[Upvar],
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
         let (upvar_name, upvar_span) =
             self.get_upvar_name_and_span_for_region(tcx, upvars, upvar_index);
-        let region_name = self.synthesize_region_name(counter);
+        let region_name = self.synthesize_region_name(renctx);
 
         Some(RegionName {
             name: region_name,
@@ -680,7 +737,7 @@
         body: &Body<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let tcx = infcx.tcx;
 
@@ -694,7 +751,7 @@
         }
 
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(fr, *counter);
+        highlight.highlighting_region_vid(fr, renctx.counter);
         let type_name = infcx.extract_type_name(&return_ty, Some(highlight)).0;
 
         let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
@@ -725,11 +782,11 @@
             // This counter value will already have been used, so this function will increment it
             // so the next value will be used next and return the region name that would have been
             // used.
-            name: self.synthesize_region_name(counter),
+            name: self.synthesize_region_name(renctx),
             source: RegionNameSource::AnonRegionFromOutput(
                 return_span,
                 mir_description.to_string(),
-                type_name
+                type_name,
             ),
         })
     }
@@ -740,7 +797,7 @@
         body: &Body<'tcx>,
         mir_def_id: DefId,
         fr: RegionVid,
-        counter: &mut usize,
+        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         // Note: generators from `async fn` yield `()`, so we don't have to
         // worry about them here.
@@ -757,7 +814,7 @@
         }
 
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(fr, *counter);
+        highlight.highlighting_region_vid(fr, renctx.counter);
         let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)).0;
 
         let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
@@ -780,16 +837,15 @@
         );
 
         Some(RegionName {
-            name: self.synthesize_region_name(counter),
+            name: self.synthesize_region_name(renctx),
             source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name),
         })
     }
 
-    /// Creates a synthetic region named `'1`, incrementing the
-    /// counter.
-    fn synthesize_region_name(&self, counter: &mut usize) -> InternedString {
-        let c = *counter;
-        *counter += 1;
+    /// Creates a synthetic region named `'1`, incrementing the counter.
+    fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> InternedString {
+        let c = renctx.counter;
+        renctx.counter += 1;
 
         InternedString::intern(&format!("'{:?}", c))
     }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 4038872..78e7943 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1,15 +1,20 @@
-use super::universal_regions::UniversalRegions;
-use crate::borrow_check::nll::constraints::graph::NormalConstraintGraph;
-use crate::borrow_check::nll::constraints::{
-    ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
+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
+    },
+    type_check::{free_region_relations::UniversalRegionRelations, Locations},
 };
-use crate::borrow_check::nll::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
-use crate::borrow_check::nll::region_infer::values::{
-    PlaceholderIndices, RegionElement, ToElementIndex,
-};
-use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
-use crate::borrow_check::nll::type_check::Locations;
 use crate::borrow_check::Upvar;
+
 use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::QueryOutlivesConstraint;
 use rustc::infer::opaque_types;
@@ -31,16 +36,16 @@
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
 use syntax_pos::Span;
 
-use std::rc::Rc;
+crate use self::error_reporting::{RegionName, RegionNameSource, RegionErrorNamingCtx};
+use self::values::{LivenessValues, RegionValueElements, RegionValues};
+use super::universal_regions::UniversalRegions;
+use super::ToRegionVid;
 
 mod dump_mir;
 mod error_reporting;
-crate use self::error_reporting::{RegionName, RegionNameSource};
 mod graphviz;
-pub mod values;
-use self::values::{LivenessValues, RegionValueElements, RegionValues};
 
-use super::ToRegionVid;
+pub mod values;
 
 pub struct RegionInferenceContext<'tcx> {
     /// Contains the definition for every region variable. Region
@@ -487,6 +492,12 @@
             errors_buffer,
         );
 
+        // If we produce any errors, we keep track of the names of all regions, so that we can use
+        // the same error names in any suggestions we produce. Note that we need names to be unique
+        // across different errors for the same MIR def so that we can make suggestions that fix
+        // multiple problems.
+        let mut region_naming = RegionErrorNamingCtx::new();
+
         self.check_universal_regions(
             infcx,
             body,
@@ -494,6 +505,7 @@
             mir_def_id,
             outlives_requirements.as_mut(),
             errors_buffer,
+            &mut region_naming,
         );
 
         self.check_member_constraints(infcx, mir_def_id, errors_buffer);
@@ -1312,6 +1324,7 @@
         mir_def_id: DefId,
         mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
         errors_buffer: &mut Vec<Diagnostic>,
+        region_naming: &mut RegionErrorNamingCtx,
     ) {
         for (fr, fr_definition) in self.definitions.iter_enumerated() {
             match fr_definition.origin {
@@ -1327,6 +1340,7 @@
                         fr,
                         &mut propagated_outlives_requirements,
                         errors_buffer,
+                        region_naming,
                     );
                 }
 
@@ -1358,6 +1372,7 @@
         longer_fr: RegionVid,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
         errors_buffer: &mut Vec<Diagnostic>,
+        region_naming: &mut RegionErrorNamingCtx,
     ) {
         debug!("check_universal_region(fr={:?})", longer_fr);
 
@@ -1385,6 +1400,7 @@
                 mir_def_id,
                 propagated_outlives_requirements,
                 errors_buffer,
+                region_naming,
             );
             return;
         }
@@ -1401,8 +1417,13 @@
                 mir_def_id,
                 propagated_outlives_requirements,
                 errors_buffer,
+                region_naming,
             ) {
                 // continuing to iterate just reports more errors than necessary
+                //
+                // FIXME It would also allow us to report more Outlives Suggestions, though, so
+                // it's not clear that that's a bad thing. Somebody should try commenting out this
+                // line and see it is actually a regression.
                 return;
             }
         }
@@ -1418,6 +1439,7 @@
         mir_def_id: DefId,
         propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
         errors_buffer: &mut Vec<Diagnostic>,
+        region_naming: &mut RegionErrorNamingCtx,
     ) -> Option<ErrorReported> {
         // If it is known that `fr: o`, carry on.
         if self.universal_region_relations.outlives(longer_fr, shorter_fr) {
@@ -1466,7 +1488,18 @@
         //
         // Note: in this case, we use the unapproximated regions to report the
         // error. This gives better error messages in some cases.
-        self.report_error(body, upvars, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
+        let db = self.report_error(
+            body,
+            upvars,
+            infcx,
+            mir_def_id,
+            longer_fr,
+            shorter_fr,
+            region_naming,
+        );
+
+        db.buffer(errors_buffer);
+
         Some(ErrorReported)
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
index 2a06653..049d83b 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
@@ -1,7 +1,7 @@
 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, Body};
+use rustc::mir::{Body, Local, Location};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::vec_linked_list as vll;
 
@@ -72,16 +72,10 @@
 
         let mut locals_with_use_data: IndexVec<Local, bool> =
             IndexVec::from_elem_n(false, body.local_decls.len());
-        live_locals
-            .iter()
-            .for_each(|&local| locals_with_use_data[local] = true);
+        live_locals.iter().for_each(|&local| locals_with_use_data[local] = true);
 
-        LocalUseMapBuild {
-            local_use_map: &mut local_use_map,
-            elements,
-            locals_with_use_data,
-        }
-        .visit_body(body);
+        LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data }
+            .visit_body(body);
 
         local_use_map
     }
@@ -151,10 +145,8 @@
         location: Location,
     ) {
         let point_index = elements.point_from_location(location);
-        let appearance_index = appearances.push(Appearance {
-            point_index,
-            next: *first_appearance,
-        });
+        let appearance_index =
+            appearances.push(Appearance { point_index, next: *first_appearance });
         *first_appearance = Some(appearance_index);
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
index 8970009..3f2ec1b 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
@@ -58,9 +58,9 @@
     };
 
     if !live_locals.is_empty() {
-        trace::trace(typeck, body, elements, flow_inits, move_data, live_locals, location_table);
+        trace::trace(typeck, body, elements, flow_inits, move_data, live_locals);
 
-        polonius::populate_var_liveness_facts(typeck, body, location_table);
+        polonius::populate_access_facts(typeck, body, location_table, move_data);
     }
 }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
index 20d7ec5..d61464b 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
@@ -1,22 +1,28 @@
 use crate::borrow_check::location::{LocationIndex, LocationTable};
+use crate::dataflow::indexes::MovePathIndex;
+use crate::dataflow::move_paths::{LookupResult, MoveData};
 use crate::util::liveness::{categorize, DefUse};
-use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{Body, Local, Location};
+use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
+use rustc::mir::{Body, Local, Location, Place};
 use rustc::ty::subst::Kind;
 use rustc::ty::Ty;
 
 use super::TypeChecker;
 
 type VarPointRelations = Vec<(Local, LocationIndex)>;
+type MovePathPointRelations = Vec<(MovePathIndex, LocationIndex)>;
 
-struct LivenessPointFactsExtractor<'me> {
+struct UseFactsExtractor<'me> {
     var_defined: &'me mut VarPointRelations,
     var_used: &'me mut VarPointRelations,
     location_table: &'me LocationTable,
+    var_drop_used: &'me mut VarPointRelations,
+    move_data: &'me MoveData<'me>,
+    path_accessed_at: &'me mut MovePathPointRelations,
 }
 
 // A Visitor to walk through the MIR and extract point-wise facts
-impl LivenessPointFactsExtractor<'_> {
+impl UseFactsExtractor<'_> {
     fn location_to_index(&self, location: Location) -> LocationIndex {
         self.location_table.mid_index(location)
     }
@@ -30,15 +36,50 @@
         debug!("LivenessFactsExtractor::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()");
+        self.var_drop_used.push((local, self.location_to_index(location)));
+    }
+
+    fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
+        debug!("LivenessFactsExtractor::insert_path_access({:?}, {:?})", path, location);
+        self.path_accessed_at.push((path, self.location_to_index(location)));
+    }
+
+    fn place_to_mpi(&self, place: &Place<'_>) -> Option<MovePathIndex> {
+        match self.move_data.rev_lookup.find(place.as_ref()) {
+            LookupResult::Exact(mpi) => Some(mpi),
+            LookupResult::Parent(mmpi) => mmpi,
+        }
+    }
 }
 
-impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> {
+impl Visitor<'tcx> for UseFactsExtractor<'_> {
     fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
         match categorize(context) {
             Some(DefUse::Def) => self.insert_def(local, location),
             Some(DefUse::Use) => self.insert_use(local, location),
+            Some(DefUse::Drop) => self.insert_drop_use(local, location),
             _ => (),
-            // NOTE: Drop handling is now done in trace()
+        }
+    }
+
+    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
+        self.super_place(place, context, location);
+        match context {
+            PlaceContext::NonMutatingUse(_) => {
+                if let Some(mpi) = self.place_to_mpi(place) {
+                    self.insert_path_access(mpi, location);
+                }
+            }
+
+            PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
+                if let Some(mpi) = self.place_to_mpi(place) {
+                    self.insert_path_access(mpi, location);
+                }
+            }
+            _ => (),
         }
     }
 }
@@ -54,23 +95,27 @@
     });
 }
 
-pub(super) fn populate_var_liveness_facts(
+pub(super) fn populate_access_facts(
     typeck: &mut TypeChecker<'_, 'tcx>,
-    mir: &Body<'tcx>,
+    body: &Body<'tcx>,
     location_table: &LocationTable,
+    move_data: &MoveData<'_>,
 ) {
     debug!("populate_var_liveness_facts()");
 
     if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
-        LivenessPointFactsExtractor {
+        UseFactsExtractor {
             var_defined: &mut facts.var_defined,
             var_used: &mut facts.var_used,
+            var_drop_used: &mut facts.var_drop_used,
+            path_accessed_at: &mut facts.path_accessed_at,
             location_table,
+            move_data,
         }
-        .visit_body(mir);
+        .visit_body(body);
     }
 
-    for (local, local_decl) in mir.local_decls.iter_enumerated() {
+    for (local, local_decl) in body.local_decls.iter_enumerated() {
         add_var_uses_regions(typeck, local, local_decl.ty);
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
index 039ed93..9b55881 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
@@ -1,4 +1,3 @@
-use crate::borrow_check::location::LocationTable;
 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;
@@ -38,7 +37,6 @@
     flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
     move_data: &MoveData<'tcx>,
     live_locals: Vec<Local>,
-    location_table: &LocationTable,
 ) {
     debug!("trace()");
 
@@ -52,7 +50,6 @@
         local_use_map,
         move_data,
         drop_data: FxHashMap::default(),
-        location_table,
     };
 
     LivenessResults::new(cx).compute_for_all_locals(live_locals);
@@ -82,9 +79,6 @@
     /// Index indicating where each variable is assigned, used, or
     /// dropped.
     local_use_map: &'me LocalUseMap,
-
-    /// Maps between a MIR Location and a LocationIndex
-    location_table: &'me LocationTable,
 }
 
 struct DropData<'tcx> {
@@ -131,12 +125,6 @@
         for local in live_locals {
             self.reset_local_state();
             self.add_defs_for(local);
-
-            // FIXME: this is temporary until we can generate our own initialization
-            if self.cx.typeck.borrowck_context.all_facts.is_some() {
-                self.add_polonius_var_initialized_on_exit_for(local)
-            }
-
             self.compute_use_live_points_for(local);
             self.compute_drop_live_points_for(local);
 
@@ -157,63 +145,6 @@
         }
     }
 
-    // WARNING: panics if self.cx.typeck.borrowck_context.all_facts != None
-    //
-    // FIXME: this analysis (the initialization tracking) should be
-    // done in Polonius, but isn't yet.
-    fn add_polonius_var_initialized_on_exit_for(&mut self, local: Local) {
-        let move_path = self.cx.move_data.rev_lookup.find_local(local);
-        let facts = self.cx.typeck.borrowck_context.all_facts.as_mut().unwrap();
-        for block in self.cx.body.basic_blocks().indices() {
-            debug!("polonius: generating initialization facts for {:?} in {:?}", local, block);
-
-            // iterate through the block, applying the effects of each statement
-            // up to and including location, and populate `var_initialized_on_exit`
-            self.cx.flow_inits.reset_to_entry_of(block);
-            let start_location = Location { block, statement_index: 0 };
-            self.cx.flow_inits.apply_local_effect(start_location);
-
-            for statement_index in 0..self.cx.body[block].statements.len() {
-                let current_location = Location { block, statement_index };
-
-                self.cx.flow_inits.reconstruct_statement_effect(current_location);
-
-                // statement has not yet taken effect:
-                if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
-                    facts
-                        .var_initialized_on_exit
-                        .push((local, self.cx.location_table.start_index(current_location)));
-                }
-
-                // statement has now taken effect
-                self.cx.flow_inits.apply_local_effect(current_location);
-
-                if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
-                    facts
-                        .var_initialized_on_exit
-                        .push((local, self.cx.location_table.mid_index(current_location)));
-                }
-            }
-
-            let terminator_location = self.cx.body.terminator_loc(block);
-
-            if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
-                facts
-                    .var_initialized_on_exit
-                    .push((local, self.cx.location_table.start_index(terminator_location)));
-            }
-
-            // apply the effects of the terminator and push it if needed
-            self.cx.flow_inits.reset_to_exit_of(block);
-
-            if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
-                facts
-                    .var_initialized_on_exit
-                    .push((local, self.cx.location_table.mid_index(terminator_location)));
-            }
-        }
-    }
-
     /// Clear the value of fields that are "per local variable".
     fn reset_local_state(&mut self) {
         self.defs.clear();
@@ -273,11 +204,6 @@
             debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,);
 
             if self.cx.initialized_at_terminator(location.block, mpi) {
-                // FIXME: this analysis (the initialization tracking) should be
-                // done in Polonius, but isn't yet.
-                if let Some(facts) = self.cx.typeck.borrowck_context.all_facts {
-                    facts.var_drop_used.push((local, self.cx.location_table.mid_index(location)));
-                }
                 if self.drop_live_at.insert(drop_point) {
                     self.drop_locations.push(location);
                     self.stack.push(drop_point);
@@ -468,13 +394,7 @@
     ) {
         debug!("add_use_live_facts_for(value={:?})", value);
 
-        Self::make_all_regions_live(
-            self.elements,
-            &mut self.typeck,
-            value,
-            live_at,
-            self.location_table,
-        )
+        Self::make_all_regions_live(self.elements, &mut self.typeck, value, live_at)
     }
 
     /// Some variable with type `live_ty` is "drop live" at `location`
@@ -525,13 +445,7 @@
         // All things in the `outlives` array may be touched by
         // the destructor and must be live at this point.
         for &kind in &drop_data.dropck_result.kinds {
-            Self::make_all_regions_live(
-                self.elements,
-                &mut self.typeck,
-                kind,
-                live_at,
-                self.location_table,
-            );
+            Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at);
 
             polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind);
         }
@@ -542,7 +456,6 @@
         typeck: &mut TypeChecker<'_, 'tcx>,
         value: impl TypeFoldable<'tcx>,
         live_at: &HybridBitSet<PointIndex>,
-        location_table: &LocationTable,
     ) {
         debug!("make_all_regions_live(value={:?})", value);
         debug!(
@@ -559,15 +472,6 @@
                 .constraints
                 .liveness_constraints
                 .add_elements(live_region_vid, live_at);
-
-            // FIXME: remove this when we can generate our own region-live-at reliably
-            if let Some(facts) = typeck.borrowck_context.all_facts {
-                for point in live_at.iter() {
-                    let loc = elements.to_location(point);
-                    facts.region_live_at.push((live_region_vid, location_table.start_index(loc)));
-                    facts.region_live_at.push((live_region_vid, location_table.mid_index(loc)));
-                }
-            }
         });
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index da1f64b..62bff34 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -421,107 +421,104 @@
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
 
-        place.iterate(|place_base, place_projection| {
-            let mut place_ty = match place_base {
-                PlaceBase::Local(index) =>
-                    PlaceTy::from_ty(self.body.local_decls[*index].ty),
-                PlaceBase::Static(box Static { kind, ty: sty, def_id }) => {
-                    let sty = self.sanitize_type(place, sty);
-                    let check_err =
-                        |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
-                         place: &Place<'tcx>,
-                         ty,
-                         sty| {
-                            if let Err(terr) = verifier.cx.eq_types(
-                                sty,
-                                ty,
-                                location.to_locations(),
-                                ConstraintCategory::Boring,
-                            ) {
-                                span_mirbug!(
-                                verifier,
-                                place,
-                                "bad promoted type ({:?}: {:?}): {:?}",
-                                ty,
-                                sty,
-                                terr
-                            );
-                            };
+        let mut place_ty = match &place.base {
+            PlaceBase::Local(index) =>
+                PlaceTy::from_ty(self.body.local_decls[*index].ty),
+            PlaceBase::Static(box Static { kind, ty: sty, def_id }) => {
+                let sty = self.sanitize_type(place, sty);
+                let check_err =
+                    |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
+                     place: &Place<'tcx>,
+                     ty,
+                     sty| {
+                        if let Err(terr) = verifier.cx.eq_types(
+                            sty,
+                            ty,
+                            location.to_locations(),
+                            ConstraintCategory::Boring,
+                        ) {
+                            span_mirbug!(
+                            verifier,
+                            place,
+                            "bad promoted type ({:?}: {:?}): {:?}",
+                            ty,
+                            sty,
+                            terr
+                        );
                         };
-                    match kind {
-                        StaticKind::Promoted(promoted, _) => {
-                            if !self.errors_reported {
-                                let promoted_body = &self.promoted[*promoted];
-                                self.sanitize_promoted(promoted_body, location);
+                    };
+                match kind {
+                    StaticKind::Promoted(promoted, _) => {
+                        if !self.errors_reported {
+                            let promoted_body = &self.promoted[*promoted];
+                            self.sanitize_promoted(promoted_body, location);
 
-                                let promoted_ty = promoted_body.return_ty();
-                                check_err(self, place, promoted_ty, sty);
-                            }
-                        }
-                        StaticKind::Static => {
-                            let ty = self.tcx().type_of(*def_id);
-                            let ty = self.cx.normalize(ty, location);
-
-                            check_err(self, place, ty, sty);
+                            let promoted_ty = promoted_body.return_ty();
+                            check_err(self, place, promoted_ty, sty);
                         }
                     }
-                    PlaceTy::from_ty(sty)
-                }
-            };
+                    StaticKind::Static => {
+                        let ty = self.tcx().type_of(*def_id);
+                        let ty = self.cx.normalize(ty, location);
 
-            // FIXME use place_projection.is_empty() when is available
-            if place.projection.is_none() {
-                if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
-                    let is_promoted = match place {
-                        Place {
-                            base: PlaceBase::Static(box Static {
-                                kind: StaticKind::Promoted(..),
-                                ..
-                            }),
-                            projection: None,
-                        } => true,
-                        _ => false,
+                        check_err(self, place, ty, sty);
+                    }
+                }
+                PlaceTy::from_ty(sty)
+            }
+        };
+
+        if place.projection.is_empty() {
+            if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
+                let is_promoted = match place {
+                    Place {
+                        base: PlaceBase::Static(box Static {
+                            kind: StaticKind::Promoted(..),
+                            ..
+                        }),
+                        projection: box [],
+                    } => true,
+                    _ => false,
+                };
+
+                if !is_promoted {
+                    let tcx = self.tcx();
+                    let trait_ref = ty::TraitRef {
+                        def_id: tcx.lang_items().copy_trait().unwrap(),
+                        substs: tcx.mk_substs_trait(place_ty.ty, &[]),
                     };
 
-                    if !is_promoted {
-                        let tcx = self.tcx();
-                        let trait_ref = ty::TraitRef {
-                            def_id: tcx.lang_items().copy_trait().unwrap(),
-                            substs: tcx.mk_substs_trait(place_ty.ty, &[]),
-                        };
-
-                        // In order to have a Copy operand, the type T of the
-                        // value must be Copy. Note that we prove that T: Copy,
-                        // rather than using the `is_copy_modulo_regions`
-                        // test. This is important because
-                        // `is_copy_modulo_regions` ignores the resulting region
-                        // obligations and assumes they pass. This can result in
-                        // bounds from Copy impls being unsoundly ignored (e.g.,
-                        // #29149). Note that we decide to use Copy before knowing
-                        // whether the bounds fully apply: in effect, the rule is
-                        // that if a value of some type could implement Copy, then
-                        // it must.
-                        self.cx.prove_trait_ref(
-                            trait_ref,
-                            location.to_locations(),
-                            ConstraintCategory::CopyBound,
-                        );
-                    }
+                    // To have a `Copy` operand, the type `T` of the
+                    // value must be `Copy`. Note that we prove that `T: Copy`,
+                    // rather than using the `is_copy_modulo_regions`
+                    // test. This is important because
+                    // `is_copy_modulo_regions` ignores the resulting region
+                    // obligations and assumes they pass. This can result in
+                    // bounds from `Copy` impls being unsoundly ignored (e.g.,
+                    // #29149). Note that we decide to use `Copy` before knowing
+                    // whether the bounds fully apply: in effect, the rule is
+                    // that if a value of some type could implement `Copy`, then
+                    // it must.
+                    self.cx.prove_trait_ref(
+                        trait_ref,
+                        location.to_locations(),
+                        ConstraintCategory::CopyBound,
+                    );
                 }
             }
+        }
 
-            for proj in place_projection {
-                if place_ty.variant_index.is_none() {
-                    if place_ty.ty.references_error() {
-                        assert!(self.errors_reported);
-                        return PlaceTy::from_ty(self.tcx().types.err);
-                    }
+        for elem in place.projection.iter() {
+            if place_ty.variant_index.is_none() {
+                if place_ty.ty.references_error() {
+                    assert!(self.errors_reported);
+                    return PlaceTy::from_ty(self.tcx().types.err);
                 }
-                place_ty = self.sanitize_projection(place_ty, &proj.elem, place, location)
             }
+            place_ty = self.sanitize_projection(place_ty, elem, place, location)
+        }
 
-            place_ty
-        })
+        place_ty
     }
 
     fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) {
@@ -1346,7 +1343,7 @@
         debug!("check_stmt: {:?}", stmt);
         let tcx = self.tcx();
         match stmt.kind {
-            StatementKind::Assign(ref place, ref rv) => {
+            StatementKind::Assign(box(ref place, ref rv)) => {
                 // Assignments to temporaries are not "interesting";
                 // they are not caused by the user, but rather artifacts
                 // of lowering. Assignments to other sorts of places *are* interesting
@@ -1354,7 +1351,7 @@
                 let category = match *place {
                     Place {
                         base: PlaceBase::Local(RETURN_PLACE),
-                        projection: None,
+                        projection: box [],
                     } => if let BorrowCheckContext {
                         universal_regions:
                             UniversalRegions {
@@ -1373,7 +1370,7 @@
                     },
                     Place {
                         base: PlaceBase::Local(l),
-                        projection: None,
+                        projection: box [],
                     } if !body.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
@@ -1453,7 +1450,7 @@
                     );
                 };
             }
-            StatementKind::AscribeUserType(ref place, variance, box ref projection) => {
+            StatementKind::AscribeUserType(box(ref place, ref projection), variance) => {
                 let place_ty = place.ty(body, tcx).ty;
                 if let Err(terr) = self.relate_type_and_user_type(
                     place_ty,
@@ -1660,7 +1657,7 @@
                 let category = match *dest {
                     Place {
                         base: PlaceBase::Local(RETURN_PLACE),
-                        projection: None,
+                        projection: box [],
                     } => {
                         if let BorrowCheckContext {
                             universal_regions:
@@ -1682,7 +1679,7 @@
                     }
                     Place {
                         base: PlaceBase::Local(l),
-                        projection: None,
+                        projection: box [],
                     } if !body.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
@@ -2416,19 +2413,21 @@
         // *p`, where the `p` has type `&'b mut Foo`, for example, we
         // need to ensure that `'b: 'a`.
 
-        let mut borrowed_projection = &borrowed_place.projection;
-
         debug!(
             "add_reborrow_constraint({:?}, {:?}, {:?})",
             location, borrow_region, borrowed_place
         );
-        while let Some(box proj) = borrowed_projection {
-            debug!("add_reborrow_constraint - iteration {:?}", borrowed_projection);
 
-            match proj.elem {
+        let mut cursor = &*borrowed_place.projection;
+        while let [proj_base @ .., elem] = cursor {
+            cursor = proj_base;
+
+            debug!("add_reborrow_constraint - iteration {:?}", elem);
+
+            match elem {
                 ProjectionElem::Deref => {
                     let tcx = self.infcx.tcx;
-                    let base_ty = Place::ty_from(&borrowed_place.base, &proj.base, body, tcx).ty;
+                    let base_ty = Place::ty_from(&borrowed_place.base, proj_base, body, tcx).ty;
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.sty {
@@ -2490,10 +2489,6 @@
                     // other field access
                 }
             }
-
-            // The "propagate" case. We need to check that our base is valid
-            // for the borrow's lifetime.
-            borrowed_projection = &proj.base;
         }
     }
 
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index 43a012e..bac0809 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -3,7 +3,7 @@
 use crate::borrow_check::AccessDepth;
 use crate::dataflow::indexes::BorrowIndex;
 use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase};
-use rustc::mir::{ProjectionElem, BorrowKind};
+use rustc::mir::BorrowKind;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::graph::dominators::Dominators;
 
@@ -133,20 +133,11 @@
 /// Determines if a given borrow is borrowing local data
 /// This is called for all Yield statements on movable generators
 pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
-    place.iterate(|place_base, place_projection| {
-        match place_base {
-            PlaceBase::Static(..) => return false,
-            PlaceBase::Local(..) => {},
-        }
+    match place.base {
+        PlaceBase::Static(_) => false,
 
-        for proj in place_projection {
-            // Reborrow of already borrowed data is ignored
-            // Any errors will be caught on the initial borrow
-            if proj.elem == ProjectionElem::Deref {
-                return false;
-            }
-        }
-
-        true
-    })
+        // Reborrow of already borrowed data is ignored
+        // Any errors will be caught on the initial borrow
+        PlaceBase::Local(_) => !place.is_indirect(),
+    }
 }
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index 5caba63..411fa5b 100644
--- a/src/librustc_mir/borrow_check/place_ext.rs
+++ b/src/librustc_mir/borrow_check/place_ext.rs
@@ -25,55 +25,54 @@
         body: &Body<'tcx>,
         locals_state_at_exit: &LocalsStateAtExit,
     ) -> bool {
-        self.iterate(|place_base, place_projection| {
-            let ignore = match place_base {
-                // If a local variable is immutable, then we only need to track borrows to guard
-                // against two kinds of errors:
-                // * The variable being dropped while still borrowed (e.g., because the fn returns
-                //   a reference to a local variable)
-                // * The variable being moved while still borrowed
-                //
-                // In particular, the variable cannot be mutated -- the "access checks" will fail --
-                // so we don't have to worry about mutation while borrowed.
-                PlaceBase::Local(index) => {
-                    match locals_state_at_exit {
-                        LocalsStateAtExit::AllAreInvalidated => false,
-                        LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
-                            let ignore = !has_storage_dead_or_moved.contains(*index) &&
-                                body.local_decls[*index].mutability == Mutability::Not;
-                            debug!("ignore_borrow: local {:?} => {:?}", index, ignore);
-                            ignore
-                        }
-                    }
-                }
-                PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) =>
-                    false,
-                PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => {
-                    tcx.is_mutable_static(*def_id)
-                }
-            };
-
-            for proj in place_projection {
-                if proj.elem == ProjectionElem::Deref {
-                    let ty = Place::ty_from(place_base, &proj.base, body, tcx).ty;
-                    match ty.sty {
-                        // For both derefs of raw pointers and `&T`
-                        // references, the original path is `Copy` and
-                        // therefore not significant.  In particular,
-                        // there is nothing the user can do to the
-                        // original path that would invalidate the
-                        // newly created reference -- and if there
-                        // were, then the user could have copied the
-                        // original path into a new variable and
-                        // borrowed *that* one, leaving the original
-                        // path unborrowed.
-                        ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => return true,
-                        _ => {}
+        let ignore = match self.base {
+            // If a local variable is immutable, then we only need to track borrows to guard
+            // against two kinds of errors:
+            // * The variable being dropped while still borrowed (e.g., because the fn returns
+            //   a reference to a local variable)
+            // * The variable being moved while still borrowed
+            //
+            // In particular, the variable cannot be mutated -- the "access checks" will fail --
+            // so we don't have to worry about mutation while borrowed.
+            PlaceBase::Local(index) => {
+                match locals_state_at_exit {
+                    LocalsStateAtExit::AllAreInvalidated => false,
+                    LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
+                        let ignore = !has_storage_dead_or_moved.contains(index) &&
+                            body.local_decls[index].mutability == Mutability::Not;
+                        debug!("ignore_borrow: local {:?} => {:?}", index, ignore);
+                        ignore
                     }
                 }
             }
+            PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) =>
+                false,
+            PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => {
+                tcx.is_mutable_static(def_id)
+            }
+        };
 
-            ignore
-        })
+        for (i, elem) in self.projection.iter().enumerate() {
+            let proj_base = &self.projection[..i];
+
+            if *elem == ProjectionElem::Deref {
+                let ty = Place::ty_from(&self.base, proj_base, body, tcx).ty;
+                if let ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) = ty.sty {
+                    // For both derefs of raw pointers and `&T`
+                    // references, the original path is `Copy` and
+                    // therefore not significant.  In particular,
+                    // there is nothing the user can do to the
+                    // original path that would invalidate the
+                    // newly created reference -- and if there
+                    // were, then the user could have copied the
+                    // original path into a new variable and
+                    // borrowed *that* one, leaving the original
+                    // path unborrowed.
+                    return true;
+                }
+            }
+        }
+
+        ignore
     }
 }
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 4f46917..dafa0b6 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -3,8 +3,7 @@
 use crate::borrow_check::{Deep, Shallow, AccessDepth};
 use rustc::hir;
 use rustc::mir::{
-    Body, BorrowKind, Place, PlaceBase, PlaceRef, Projection, ProjectionElem, ProjectionsIter,
-    StaticKind,
+    Body, BorrowKind, Place, PlaceBase, PlaceElem, PlaceRef, ProjectionElem, StaticKind,
 };
 use rustc::ty::{self, TyCtxt};
 use std::cmp::max;
@@ -67,39 +66,35 @@
     // it's so common that it's a speed win to check for it first.
     if let Place {
         base: PlaceBase::Local(l1),
-        projection: None,
+        projection: box [],
     } = borrow_place {
         if let PlaceRef {
             base: PlaceBase::Local(l2),
-            projection: None,
+            projection: [],
         } = access_place {
             return l1 == l2;
         }
     }
 
-    borrow_place.iterate(|borrow_base, borrow_projections| {
-        access_place.iterate(|access_base, access_projections| {
-            place_components_conflict(
-                tcx,
-                param_env,
-                body,
-                (borrow_base, borrow_projections),
-                borrow_kind,
-                (access_base, access_projections),
-                access,
-                bias,
-            )
-        })
-    })
+    place_components_conflict(
+        tcx,
+        param_env,
+        body,
+        borrow_place,
+        borrow_kind,
+        access_place,
+        access,
+        bias,
+    )
 }
 
 fn place_components_conflict<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
-    borrow_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>),
+    borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
-    access_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>),
+    access_place: PlaceRef<'_, 'tcx>,
     access: AccessDepth,
     bias: PlaceConflictBias,
 ) -> bool {
@@ -145,8 +140,8 @@
     //    and either equal or disjoint.
     //  - If we did run out of access, the borrow can access a part of it.
 
-    let borrow_base = borrow_projections.0;
-    let access_base = access_projections.0;
+    let borrow_base = &borrow_place.base;
+    let access_base = access_place.base;
 
     match place_base_conflict(tcx, param_env, borrow_base, access_base) {
         Overlap::Arbitrary => {
@@ -163,147 +158,157 @@
         }
     }
 
-    let mut borrow_projections = borrow_projections.1;
-    let mut access_projections = access_projections.1;
+    // loop invariant: borrow_c is always either equal to access_c or disjoint from it.
+    for (i, (borrow_c, access_c)) in
+        borrow_place.projection.iter().zip(access_place.projection.iter()).enumerate()
+    {
+        debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c);
+        let borrow_proj_base = &borrow_place.projection[..i];
 
-    loop {
-        // loop invariant: borrow_c is always either equal to access_c or disjoint from it.
-        if let Some(borrow_c) = borrow_projections.next() {
-            debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c);
+        debug!("borrow_conflicts_with_place: access_c = {:?}", access_c);
 
-            if let Some(access_c) = access_projections.next() {
-                debug!("borrow_conflicts_with_place: access_c = {:?}", access_c);
-
-                // Borrow and access path both have more components.
+        // Borrow and access path both have more components.
+        //
+        // Examples:
+        //
+        // - borrow of `a.(...)`, access to `a.(...)`
+        // - borrow of `a.(...)`, access to `b.(...)`
+        //
+        // Here we only see the components we have checked so
+        // far (in our examples, just the first component). We
+        // check whether the components being borrowed vs
+        // accessed are disjoint (as in the second example,
+        // but not the first).
+        match place_projection_conflict(
+            tcx,
+            body,
+            borrow_base,
+            borrow_proj_base,
+            borrow_c,
+            access_c,
+            bias,
+        ) {
+            Overlap::Arbitrary => {
+                // We have encountered different fields of potentially
+                // the same union - the borrow now partially overlaps.
                 //
-                // Examples:
+                // There is no *easy* way of comparing the fields
+                // further on, because they might have different types
+                // (e.g., borrows of `u.a.0` and `u.b.y` where `.0` and
+                // `.y` come from different structs).
                 //
-                // - borrow of `a.(...)`, access to `a.(...)`
-                // - borrow of `a.(...)`, access to `b.(...)`
-                //
-                // Here we only see the components we have checked so
-                // far (in our examples, just the first component). We
-                // check whether the components being borrowed vs
-                // accessed are disjoint (as in the second example,
-                // but not the first).
-                match place_projection_conflict(tcx, body, borrow_base, borrow_c, access_c, bias) {
-                    Overlap::Arbitrary => {
-                        // We have encountered different fields of potentially
-                        // the same union - the borrow now partially overlaps.
-                        //
-                        // There is no *easy* way of comparing the fields
-                        // further on, because they might have different types
-                        // (e.g., borrows of `u.a.0` and `u.b.y` where `.0` and
-                        // `.y` come from different structs).
-                        //
-                        // We could try to do some things here - e.g., count
-                        // dereferences - but that's probably not a good
-                        // idea, at least for now, so just give up and
-                        // report a conflict. This is unsafe code anyway so
-                        // the user could always use raw pointers.
-                        debug!("borrow_conflicts_with_place: arbitrary -> conflict");
-                        return true;
-                    }
-                    Overlap::EqualOrDisjoint => {
-                        // This is the recursive case - proceed to the next element.
-                    }
-                    Overlap::Disjoint => {
-                        // We have proven the borrow disjoint - further
-                        // projections will remain disjoint.
-                        debug!("borrow_conflicts_with_place: disjoint");
-                        return false;
-                    }
-                }
-            } else {
-                // Borrow path is longer than the access path. Examples:
-                //
-                // - borrow of `a.b.c`, access to `a.b`
-                //
-                // Here, we know that the borrow can access a part of
-                // our place. This is a conflict if that is a part our
-                // access cares about.
-
-                let base = &borrow_c.base;
-                let elem = &borrow_c.elem;
-                let base_ty = Place::ty_from(borrow_base, base, body, tcx).ty;
-
-                match (elem, &base_ty.sty, access) {
-                    (_, _, Shallow(Some(ArtificialField::ArrayLength)))
-                    | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => {
-                        // The array length is like  additional fields on the
-                        // type; it does not overlap any existing data there.
-                        // Furthermore, if cannot actually be a prefix of any
-                        // borrowed place (at least in MIR as it is currently.)
-                        //
-                        // e.g., a (mutable) borrow of `a[5]` while we read the
-                        // array length of `a`.
-                        debug!("borrow_conflicts_with_place: implicit field");
-                        return false;
-                    }
-
-                    (ProjectionElem::Deref, _, Shallow(None)) => {
-                        // e.g., a borrow of `*x.y` while we shallowly access `x.y` or some
-                        // prefix thereof - the shallow access can't touch anything behind
-                        // the pointer.
-                        debug!("borrow_conflicts_with_place: shallow access behind ptr");
-                        return false;
-                    }
-                    (ProjectionElem::Deref, ty::Ref(_, _, hir::MutImmutable), _) => {
-                        // Shouldn't be tracked
-                        bug!("Tracking borrow behind shared reference.");
-                    }
-                    (ProjectionElem::Deref, ty::Ref(_, _, hir::MutMutable), AccessDepth::Drop) => {
-                        // Values behind a mutable reference are not access either by dropping a
-                        // value, or by StorageDead
-                        debug!("borrow_conflicts_with_place: drop access behind ptr");
-                        return false;
-                    }
-
-                    (ProjectionElem::Field { .. }, ty::Adt(def, _), AccessDepth::Drop) => {
-                        // Drop can read/write arbitrary projections, so places
-                        // conflict regardless of further projections.
-                        if def.has_dtor(tcx) {
-                            return true;
-                        }
-                    }
-
-                    (ProjectionElem::Deref, _, Deep)
-                    | (ProjectionElem::Deref, _, AccessDepth::Drop)
-                    | (ProjectionElem::Field { .. }, _, _)
-                    | (ProjectionElem::Index { .. }, _, _)
-                    | (ProjectionElem::ConstantIndex { .. }, _, _)
-                    | (ProjectionElem::Subslice { .. }, _, _)
-                    | (ProjectionElem::Downcast { .. }, _, _) => {
-                        // Recursive case. This can still be disjoint on a
-                        // further iteration if this a shallow access and
-                        // there's a deref later on, e.g., a borrow
-                        // of `*x.y` while accessing `x`.
-                    }
-                }
-            }
-        } else {
-            // Borrow path ran out but access path may not
-            // have. Examples:
-            //
-            // - borrow of `a.b`, access to `a.b.c`
-            // - borrow of `a.b`, access to `a.b`
-            //
-            // In the first example, where we didn't run out of
-            // access, the borrow can access all of our place, so we
-            // have a conflict.
-            //
-            // If the second example, where we did, then we still know
-            // that the borrow can access a *part* of our place that
-            // our access cares about, so we still have a conflict.
-            if borrow_kind == BorrowKind::Shallow && access_projections.next().is_some() {
-                debug!("borrow_conflicts_with_place: shallow borrow");
-                return false;
-            } else {
-                debug!("borrow_conflicts_with_place: full borrow, CONFLICT");
+                // We could try to do some things here - e.g., count
+                // dereferences - but that's probably not a good
+                // idea, at least for now, so just give up and
+                // report a conflict. This is unsafe code anyway so
+                // the user could always use raw pointers.
+                debug!("borrow_conflicts_with_place: arbitrary -> conflict");
                 return true;
             }
+            Overlap::EqualOrDisjoint => {
+                // This is the recursive case - proceed to the next element.
+            }
+            Overlap::Disjoint => {
+                // We have proven the borrow disjoint - further
+                // projections will remain disjoint.
+                debug!("borrow_conflicts_with_place: disjoint");
+                return false;
+            }
         }
     }
+
+    if borrow_place.projection.len() > access_place.projection.len() {
+        for (i, elem) in borrow_place.projection[access_place.projection.len()..].iter().enumerate()
+        {
+            // Borrow path is longer than the access path. Examples:
+            //
+            // - borrow of `a.b.c`, access to `a.b`
+            //
+            // Here, we know that the borrow can access a part of
+            // our place. This is a conflict if that is a part our
+            // access cares about.
+
+            let proj_base = &borrow_place.projection[..access_place.projection.len() + i];
+            let base_ty = Place::ty_from(borrow_base, proj_base, body, tcx).ty;
+
+            match (elem, &base_ty.sty, access) {
+                (_, _, Shallow(Some(ArtificialField::ArrayLength)))
+                | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => {
+                    // The array length is like  additional fields on the
+                    // type; it does not overlap any existing data there.
+                    // Furthermore, if cannot actually be a prefix of any
+                    // borrowed place (at least in MIR as it is currently.)
+                    //
+                    // e.g., a (mutable) borrow of `a[5]` while we read the
+                    // array length of `a`.
+                    debug!("borrow_conflicts_with_place: implicit field");
+                    return false;
+                }
+
+                (ProjectionElem::Deref, _, Shallow(None)) => {
+                    // e.g., a borrow of `*x.y` while we shallowly access `x.y` or some
+                    // prefix thereof - the shallow access can't touch anything behind
+                    // the pointer.
+                    debug!("borrow_conflicts_with_place: shallow access behind ptr");
+                    return false;
+                }
+                (ProjectionElem::Deref, ty::Ref(_, _, hir::MutImmutable), _) => {
+                    // Shouldn't be tracked
+                    bug!("Tracking borrow behind shared reference.");
+                }
+                (ProjectionElem::Deref, ty::Ref(_, _, hir::MutMutable), AccessDepth::Drop) => {
+                    // Values behind a mutable reference are not access either by dropping a
+                    // value, or by StorageDead
+                    debug!("borrow_conflicts_with_place: drop access behind ptr");
+                    return false;
+                }
+
+                (ProjectionElem::Field { .. }, ty::Adt(def, _), AccessDepth::Drop) => {
+                    // Drop can read/write arbitrary projections, so places
+                    // conflict regardless of further projections.
+                    if def.has_dtor(tcx) {
+                        return true;
+                    }
+                }
+
+                (ProjectionElem::Deref, _, Deep)
+                | (ProjectionElem::Deref, _, AccessDepth::Drop)
+                | (ProjectionElem::Field { .. }, _, _)
+                | (ProjectionElem::Index { .. }, _, _)
+                | (ProjectionElem::ConstantIndex { .. }, _, _)
+                | (ProjectionElem::Subslice { .. }, _, _)
+                | (ProjectionElem::Downcast { .. }, _, _) => {
+                    // Recursive case. This can still be disjoint on a
+                    // further iteration if this a shallow access and
+                    // there's a deref later on, e.g., a borrow
+                    // of `*x.y` while accessing `x`.
+                }
+            }
+        }
+    }
+
+    // Borrow path ran out but access path may not
+    // have. Examples:
+    //
+    // - borrow of `a.b`, access to `a.b.c`
+    // - borrow of `a.b`, access to `a.b`
+    //
+    // In the first example, where we didn't run out of
+    // access, the borrow can access all of our place, so we
+    // have a conflict.
+    //
+    // If the second example, where we did, then we still know
+    // that the borrow can access a *part* of our place that
+    // our access cares about, so we still have a conflict.
+    if borrow_kind == BorrowKind::Shallow
+        && borrow_place.projection.len() < access_place.projection.len()
+    {
+        debug!("borrow_conflicts_with_place: shallow borrow");
+        false
+    } else {
+        debug!("borrow_conflicts_with_place: full borrow, CONFLICT");
+        true
+    }
 }
 
 // Given that the bases of `elem1` and `elem2` are always either equal
@@ -381,11 +386,12 @@
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     pi1_base: &PlaceBase<'tcx>,
-    pi1: &Projection<'tcx>,
-    pi2: &Projection<'tcx>,
+    pi1_proj_base: &[PlaceElem<'tcx>],
+    pi1_elem: &PlaceElem<'tcx>,
+    pi2_elem: &PlaceElem<'tcx>,
     bias: PlaceConflictBias,
 ) -> Overlap {
-    match (&pi1.elem, &pi2.elem) {
+    match (pi1_elem, pi2_elem) {
         (ProjectionElem::Deref, ProjectionElem::Deref) => {
             // derefs (e.g., `*x` vs. `*x`) - recur.
             debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
@@ -397,7 +403,7 @@
                 debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
                 Overlap::EqualOrDisjoint
             } else {
-                let ty = Place::ty_from(pi1_base, &pi1.base, body, tcx).ty;
+                let ty = Place::ty_from(pi1_base, pi1_proj_base, body, tcx).ty;
                 match ty.sty {
                     ty::Adt(def, _) if def.is_union() => {
                         // Different fields of a union, we are basically stuck.
@@ -493,7 +499,7 @@
             // element (like -1 in Python) and `min_length` the first.
             // Therefore, `min_length - offset_from_end` gives the minimal possible
             // offset from the beginning
-            if *offset_from_begin >= min_length - offset_from_end {
+            if *offset_from_begin >= *min_length - *offset_from_end {
                 debug!("place_element_conflict: DISJOINT-OR-EQ-ARRAY-CONSTANT-INDEX-FE");
                 Overlap::EqualOrDisjoint
             } else {
@@ -538,8 +544,8 @@
         | (ProjectionElem::Subslice { .. }, _)
         | (ProjectionElem::Downcast(..), _) => bug!(
             "mismatched projections in place_element_conflict: {:?} and {:?}",
-            pi1,
-            pi2
+            pi1_elem,
+            pi2_elem
         ),
     }
 }
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index 4c6be23..0a268ec 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -19,17 +19,9 @@
 
 impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> {
     fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool {
-        let mut cursor = other.projection;
-        loop {
-            if self.projection == cursor {
-                return self.base == other.base;
-            }
-
-            match cursor {
-                None => return false,
-                Some(proj) => cursor = &proj.base,
-            }
-        }
+        self.base == other.base
+            && self.projection.len() <= other.projection.len()
+            && self.projection == &other.projection[..self.projection.len()]
     }
 }
 
@@ -81,112 +73,113 @@
         // downcasts here, but may return a base of a downcast).
 
         'cursor: loop {
-            let proj = match &cursor {
+            match &cursor {
                 PlaceRef {
                     base: PlaceBase::Local(_),
-                    projection: None,
+                    projection: [],
                 }
                 | // search yielded this leaf
                 PlaceRef {
                     base: PlaceBase::Static(_),
-                    projection: None,
+                    projection: [],
                 } => {
                     self.next = None;
                     return Some(cursor);
                 }
                 PlaceRef {
                     base: _,
-                    projection: Some(proj),
-                } => proj,
-            };
+                    projection: [proj_base @ .., elem],
+                } => {
+                    match elem {
+                        ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
+                            // FIXME: add union handling
+                            self.next = Some(PlaceRef {
+                                base: cursor.base,
+                                projection: proj_base,
+                            });
+                            return Some(cursor);
+                        }
+                        ProjectionElem::Downcast(..) |
+                        ProjectionElem::Subslice { .. } |
+                        ProjectionElem::ConstantIndex { .. } |
+                        ProjectionElem::Index(_) => {
+                            cursor = PlaceRef {
+                                base: cursor.base,
+                                projection: proj_base,
+                            };
+                            continue 'cursor;
+                        }
+                        ProjectionElem::Deref => {
+                            // (handled below)
+                        }
+                    }
 
-            match proj.elem {
-                ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
-                    // FIXME: add union handling
-                    self.next = Some(PlaceRef {
-                        base: cursor.base,
-                        projection: &proj.base,
-                    });
-                    return Some(cursor);
-                }
-                ProjectionElem::Downcast(..) |
-                ProjectionElem::Subslice { .. } |
-                ProjectionElem::ConstantIndex { .. } |
-                ProjectionElem::Index(_) => {
-                    cursor = PlaceRef {
-                        base: cursor.base,
-                        projection: &proj.base,
-                    };
-                    continue 'cursor;
-                }
-                ProjectionElem::Deref => {
-                    // (handled below)
-                }
-            }
+                    assert_eq!(*elem, ProjectionElem::Deref);
 
-            assert_eq!(proj.elem, ProjectionElem::Deref);
+                    match self.kind {
+                        PrefixSet::Shallow => {
+                            // Shallow prefixes are found by stripping away
+                            // fields, but stop at *any* dereference.
+                            // So we can just stop the traversal now.
+                            self.next = None;
+                            return Some(cursor);
+                        }
+                        PrefixSet::All => {
+                            // All prefixes: just blindly enqueue the base
+                            // of the projection.
+                            self.next = Some(PlaceRef {
+                                base: cursor.base,
+                                projection: proj_base,
+                            });
+                            return Some(cursor);
+                        }
+                        PrefixSet::Supporting => {
+                            // Fall through!
+                        }
+                    }
 
-            match self.kind {
-                PrefixSet::Shallow => {
-                    // shallow prefixes are found by stripping away
-                    // fields, but stop at *any* dereference.
-                    // So we can just stop the traversal now.
-                    self.next = None;
-                    return Some(cursor);
-                }
-                PrefixSet::All => {
-                    // all prefixes: just blindly enqueue the base
-                    // of the projection.
-                    self.next = Some(PlaceRef {
-                        base: cursor.base,
-                        projection: &proj.base,
-                    });
-                    return Some(cursor);
-                }
-                PrefixSet::Supporting => {
-                    // fall through!
-                }
-            }
+                    assert_eq!(self.kind, PrefixSet::Supporting);
+                    // Supporting prefixes: strip away fields and
+                    // derefs, except we stop at the deref of a shared
+                    // reference.
 
-            assert_eq!(self.kind, PrefixSet::Supporting);
-            // supporting prefixes: strip away fields and
-            // derefs, except we stop at the deref of a shared
-            // reference.
+                    let ty = Place::ty_from(cursor.base, proj_base, self.body, self.tcx).ty;
+                    match ty.sty {
+                        ty::RawPtr(_) |
+                        ty::Ref(
+                            _, /*rgn*/
+                            _, /*ty*/
+                            hir::MutImmutable
+                            ) => {
+                            // don't continue traversing over derefs of raw pointers or shared
+                            // borrows.
+                            self.next = None;
+                            return Some(cursor);
+                        }
 
-            let ty = Place::ty_from(cursor.base, &proj.base, self.body, self.tcx).ty;
-            match ty.sty {
-                ty::RawPtr(_) |
-                ty::Ref(
-                    _, /*rgn*/
-                    _, /*ty*/
-                    hir::MutImmutable
-                    ) => {
-                    // don't continue traversing over derefs of raw pointers or shared borrows.
-                    self.next = None;
-                    return Some(cursor);
+                        ty::Ref(
+                            _, /*rgn*/
+                            _, /*ty*/
+                            hir::MutMutable,
+                            ) => {
+                            self.next = Some(PlaceRef {
+                                base: cursor.base,
+                                projection: proj_base,
+                            });
+                            return Some(cursor);
+                        }
+
+                        ty::Adt(..) if ty.is_box() => {
+                            self.next = Some(PlaceRef {
+                                base: cursor.base,
+                                projection: proj_base,
+                            });
+                            return Some(cursor);
+                        }
+
+                        _ => panic!("unknown type fed to Projection Deref."),
+                    }
                 }
-
-                ty::Ref(
-                    _, /*rgn*/
-                    _, /*ty*/
-                    hir::MutMutable,
-                    ) => {
-                    self.next = Some(PlaceRef {
-                        base: cursor.base,
-                        projection: &proj.base,
-                    });
-                    return Some(cursor);
-                }
-
-                ty::Adt(..) if ty.is_box() => {
-                    self.next = Some(PlaceRef {
-                        base: cursor.base,
-                        projection: &proj.base,
-                    });
-                    return Some(cursor);
-                }
-
-                _ => panic!("unknown type fed to Projection Deref."),
             }
         }
     }
diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs
index 2587d14..695080d 100644
--- a/src/librustc_mir/borrow_check/used_muts.rs
+++ b/src/librustc_mir/borrow_check/used_muts.rs
@@ -89,7 +89,7 @@
         _location: Location,
     ) {
         match &statement.kind {
-            StatementKind::Assign(into, _) => {
+            StatementKind::Assign(box(into, _)) => {
                 if let PlaceBase::Local(local) = into.base {
                     debug!(
                         "visit_statement: statement={:?} local={:?} \
@@ -120,7 +120,7 @@
                 );
                 if let Place {
                     base: PlaceBase::Local(user_local),
-                    projection: None,
+                    projection: box [],
                 } = path.place {
                     self.mbcx.used_mut.insert(user_local);
                 }
diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs
index 778d1e7..3ed6b4f 100644
--- a/src/librustc_mir/build/cfg.rs
+++ b/src/librustc_mir/build/cfg.rs
@@ -37,7 +37,7 @@
                        rvalue: Rvalue<'tcx>) {
         self.push(block, Statement {
             source_info,
-            kind: StatementKind::Assign(place.clone(), box rvalue)
+            kind: StatementKind::Assign(box(place.clone(), rvalue))
         });
     }
 
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs
index 98cf4bb..09b33c6 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -129,7 +129,7 @@
                     kind: StaticKind::Static,
                     def_id: id,
                 })),
-                projection: None,
+                projection: box [],
             }),
 
             ExprKind::PlaceTypeAscription { source, user_ty } => {
@@ -147,9 +147,11 @@
                         Statement {
                             source_info,
                             kind: StatementKind::AscribeUserType(
-                                place.clone(),
+                                box(
+                                    place.clone(),
+                                    UserTypeProjection { base: annotation_index, projs: vec![], }
+                                ),
                                 Variance::Invariant,
-                                box UserTypeProjection { base: annotation_index, projs: vec![], },
                             ),
                         },
                     );
@@ -174,9 +176,11 @@
                         Statement {
                             source_info,
                             kind: StatementKind::AscribeUserType(
-                                Place::from(temp.clone()),
+                                box(
+                                    Place::from(temp.clone()),
+                                    UserTypeProjection { base: annotation_index, projs: vec![], },
+                                ),
                                 Variance::Invariant,
-                                box UserTypeProjection { base: annotation_index, projs: vec![], },
                             ),
                         },
                     );
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 1a186fa..7dfe98c 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -500,14 +500,11 @@
         let mutability = match arg_place {
             Place {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: box [],
             } => this.local_decls[local].mutability,
             Place {
                 base: PlaceBase::Local(local),
-                projection: Some(box Projection {
-                    base: None,
-                    elem: ProjectionElem::Deref,
-                })
+                projection: box [ProjectionElem::Deref],
             } => {
                 debug_assert!(
                     this.local_decls[local].is_ref_for_guard(),
@@ -517,24 +514,19 @@
             }
             Place {
                 ref base,
-                projection: Some(box Projection {
-                    base: ref base_proj,
-                    elem: ProjectionElem::Field(upvar_index, _),
-                }),
+                projection: box [ref proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             }
             | Place {
                 ref base,
-                projection: Some(box Projection {
-                    base: Some(box Projection {
-                        base: ref base_proj,
-                        elem: ProjectionElem::Field(upvar_index, _),
-                    }),
-                    elem: ProjectionElem::Deref,
-                }),
+                projection: box [
+                    ref proj_base @ ..,
+                    ProjectionElem::Field(upvar_index, _),
+                    ProjectionElem::Deref
+                ],
             } => {
                 let place = PlaceRef {
                     base,
-                    projection: base_proj,
+                    projection: proj_base,
                 };
 
                 // Not projected from the implicit `self` in a closure.
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 889861b..45f4a16 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -301,7 +301,7 @@
                 // Create a "fake" temporary variable so that we check that the
                 // value is Sized. Usually, this is caught in type checking, but
                 // in the case of box expr there is no such check.
-                if destination.projection.is_some() {
+                if !destination.projection.is_empty() {
                     this.local_decls
                         .push(LocalDecl::new_temp(expr.ty, expr.span));
                 }
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 94323b1..2b0237c 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -135,7 +135,7 @@
             source_info,
             kind: StatementKind::FakeRead(
                 FakeReadCause::ForMatchedPlace,
-                scrutinee_place.clone(),
+                box(scrutinee_place.clone()),
             ),
         });
 
@@ -320,7 +320,7 @@
                     block,
                     Statement {
                         source_info,
-                        kind: StatementKind::FakeRead(FakeReadCause::ForLet, place),
+                        kind: StatementKind::FakeRead(FakeReadCause::ForLet, box(place)),
                     },
                 );
 
@@ -362,12 +362,12 @@
                     block,
                     Statement {
                         source_info: pattern_source_info,
-                        kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()),
+                        kind: StatementKind::FakeRead(FakeReadCause::ForLet, box(place.clone())),
                     },
                 );
 
                 let ty_source_info = self.source_info(user_ty_span);
-                let user_ty = box pat_ascription_ty.user_ty(
+                let user_ty = pat_ascription_ty.user_ty(
                     &mut self.canonical_user_type_annotations,
                     place.ty(&self.local_decls, self.hir.tcx()).ty,
                     ty_source_info.span,
@@ -377,7 +377,10 @@
                     Statement {
                         source_info: ty_source_info,
                         kind: StatementKind::AscribeUserType(
-                            place,
+                            box(
+                                place,
+                                user_ty,
+                            ),
                             // We always use invariant as the variance here. This is because the
                             // variance field from the ascription refers to the variance to use
                             // when applying the type to the value being matched, but this
@@ -393,7 +396,6 @@
                             // contrast, is intended to be used to relate `T` to the type of
                             // `<expr>`.
                             ty::Variance::Invariant,
-                            user_ty,
                         ),
                     },
                 );
@@ -942,16 +944,15 @@
             for Binding { source, .. }
                 in matched_candidates.iter().flat_map(|candidate| &candidate.bindings)
             {
-                let mut cursor = &source.projection;
-                while let Some(box Projection { base, elem }) = cursor {
-                    cursor = base;
-                    if let ProjectionElem::Deref = elem {
-                        fake_borrows.insert(Place {
-                            base: source.base.clone(),
-                            projection: cursor.clone(),
-                        });
-                        break;
-                    }
+                if let Some(i) =
+                    source.projection.iter().rposition(|elem| *elem == ProjectionElem::Deref)
+                {
+                    let proj_base = &source.projection[..i];
+
+                    fake_borrows.insert(Place {
+                        base: source.base.clone(),
+                        projection: proj_base.to_vec().into_boxed_slice(),
+                    });
                 }
             }
         }
@@ -1295,18 +1296,19 @@
         // Insert a Shallow borrow of the prefixes of any fake borrows.
         for place in fake_borrows
         {
-            let mut prefix_cursor = &place.projection;
-            while let Some(box Projection { base, elem }) = prefix_cursor {
+            let mut cursor = &*place.projection;
+            while let [proj_base @ .., elem] = cursor {
+                cursor = proj_base;
+
                 if let ProjectionElem::Deref = elem {
                     // Insert a shallow borrow after a deref. For other
                     // projections the borrow of prefix_cursor will
                     // conflict with any mutation of base.
                     all_fake_borrows.push(PlaceRef {
                         base: &place.base,
-                        projection: base,
+                        projection: proj_base,
                     });
                 }
-                prefix_cursor = base;
             }
 
             all_fake_borrows.push(place.as_ref());
@@ -1345,13 +1347,9 @@
     /// any, and then branches to the arm. Returns the block for the case where
     /// the guard fails.
     ///
-    /// Note: we check earlier that if there is a guard, there cannot be move
-    /// bindings (unless feature(bind_by_move_pattern_guards) is used). This
-    /// isn't really important for the self-consistency of this fn, but the
-    /// reason for it should be clear: after we've done the assignments, if
-    /// there were move bindings, further tests would be a use-after-move.
-    /// bind_by_move_pattern_guards avoids this by only moving the binding once
-    /// the guard has evaluated to true (see below).
+    /// Note: we do not check earlier that if there is a guard,
+    /// there cannot be move bindings. We avoid a use-after-move by only
+    /// moving the binding once the guard has evaluated to true (see below).
     fn bind_and_guard_matched_candidate<'pat>(
         &mut self,
         candidate: Candidate<'pat, 'tcx>,
@@ -1493,7 +1491,7 @@
                     BorrowKind::Shallow,
                     Place {
                         base: place.base.clone(),
-                        projection: place.projection.clone(),
+                        projection: place.projection.to_vec().into_boxed_slice(),
                     },
                 );
                 self.cfg.push_assign(
@@ -1524,7 +1522,7 @@
                     source_info: guard_end,
                     kind: StatementKind::FakeRead(
                         FakeReadCause::ForMatchGuard,
-                        Place::from(temp),
+                        box(Place::from(temp)),
                     ),
                 });
             }
@@ -1574,7 +1572,7 @@
                     post_guard_block,
                     Statement {
                         source_info: guard_end,
-                        kind: StatementKind::FakeRead(FakeReadCause::ForGuardBinding, place),
+                        kind: StatementKind::FakeRead(FakeReadCause::ForGuardBinding, box(place)),
                     },
                 );
             }
@@ -1607,7 +1605,7 @@
                 ascription.user_ty,
             );
 
-            let user_ty = box ascription.user_ty.clone().user_ty(
+            let user_ty = ascription.user_ty.clone().user_ty(
                 &mut self.canonical_user_type_annotations,
                 ascription.source.ty(&self.local_decls, self.hir.tcx()).ty,
                 source_info.span
@@ -1617,9 +1615,11 @@
                 Statement {
                     source_info,
                     kind: StatementKind::AscribeUserType(
-                        ascription.source.clone(),
+                        box(
+                            ascription.source.clone(),
+                            user_ty,
+                        ),
                         ascription.variance,
-                        user_ty,
                     ),
                 },
             );
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 7ab0bf7..647d751 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -609,7 +609,7 @@
         unpack!(block = builder.in_breakable_scope(
             None,
             START_BLOCK,
-            Place::RETURN_PLACE,
+            Place::return_place(),
             |builder| {
                 builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
                     builder.args_and_body(block, &arguments, arg_scope, &body.value)
@@ -670,7 +670,7 @@
     let mut block = START_BLOCK;
     let ast_expr = &tcx.hir().body(body_id).value;
     let expr = builder.hir.mirror(ast_expr);
-    unpack!(block = builder.into_expr(&Place::RETURN_PLACE, block, expr));
+    unpack!(block = builder.into_expr(&Place::return_place(), block, expr));
 
     let source_info = builder.source_info(span);
     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
@@ -871,7 +871,7 @@
         }
 
         let body = self.hir.mirror(ast_body);
-        self.into(&Place::RETURN_PLACE, block, body)
+        self.into(&Place::return_place(), block, body)
     }
 
     fn set_correct_source_scope_for_arg(
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index a04c041..ee6d42d 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -314,7 +314,7 @@
         match target {
             BreakableTarget::Return => {
                 let scope = &self.breakable_scopes[0];
-                if scope.break_destination != Place::RETURN_PLACE {
+                if scope.break_destination != Place::return_place() {
                     span_bug!(span, "`return` in item with no return scope");
                 }
                 (scope.break_block, scope.region_scope, Some(scope.break_destination.clone()))
@@ -853,11 +853,11 @@
             _ if self.local_scope().is_none() => (),
             Operand::Copy(Place {
                 base: PlaceBase::Local(cond_temp),
-                projection: None,
+                projection: box [],
             })
             | Operand::Move(Place {
                 base: PlaceBase::Local(cond_temp),
-                projection: None,
+                projection: box [],
             }) => {
                 // Manually drop the condition on both branches.
                 let top_scope = self.scopes.scopes.last_mut().unwrap();
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 5aa487d..4351598 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -15,6 +15,7 @@
 use rustc::ty::layout::{self, LayoutOf, VariantIdx};
 use rustc::traits::Reveal;
 use rustc_data_structures::fx::FxHashMap;
+use crate::interpret::eval_nullary_intrinsic;
 
 use syntax::source_map::{Span, DUMMY_SP};
 
@@ -134,9 +135,8 @@
     ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
     cid: GlobalId<'tcx>,
     body: &'mir mir::Body<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
 ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
-    debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
+    debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
     let tcx = ecx.tcx.tcx;
     let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
     assert!(!layout.is_unsized());
@@ -162,7 +162,6 @@
         ecx,
         cid.instance.def_id(),
         ret,
-        param_env,
     )?;
 
     debug!("eval_body_using_ecx done: {:?}", *ret);
@@ -383,7 +382,7 @@
             return Ok(());
         }
         // An intrinsic that we do not support
-        let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..];
+        let intrinsic_name = ecx.tcx.item_name(instance.def_id());
         Err(
             ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into()
         )
@@ -533,8 +532,8 @@
 
 pub fn note_on_undefined_behavior_error() -> &'static str {
     "The rules on what exactly is undefined behavior aren't clear, \
-    so this check might be overzealous. Please open an issue on the rust compiler \
-    repository if you believe it should not be considered undefined behavior"
+     so this check might be overzealous. Please open an issue on the rustc \
+     repository if you believe it should not be considered undefined behavior."
 }
 
 fn validate_and_turn_into_const<'tcx>(
@@ -589,7 +588,7 @@
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
 ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
-    // see comment in const_eval_provider for what we're doing here
+    // see comment in const_eval_raw_provider for what we're doing here
     if key.param_env.reveal == Reveal::All {
         let mut key = key.clone();
         key.param_env.reveal = Reveal::UserFacing;
@@ -604,6 +603,23 @@
             other => return other,
         }
     }
+
+    // We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
+    // Catch such calls and evaluate them instead of trying to load a constant's MIR.
+    if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
+        let ty = key.value.instance.ty(tcx);
+        let substs = match ty.sty {
+            ty::FnDef(_, substs) => substs,
+            _ => bug!("intrinsic with type {:?}", ty),
+        };
+        return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs)
+            .map_err(|error| {
+                let span = tcx.def_span(def_id);
+                let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span };
+                error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic")
+            })
+    }
+
     tcx.const_eval_raw(key).and_then(|val| {
         validate_and_turn_into_const(tcx, val, key)
     })
@@ -658,7 +674,7 @@
 
     let res = ecx.load_mir(cid.instance.def, cid.promoted);
     res.and_then(
-        |body| eval_body_using_ecx(&mut ecx, cid, body, key.param_env)
+        |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/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index c071b31..444cc00 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -10,19 +10,17 @@
                                         path: MovePathIndex,
                                         mut cond: F)
                                         -> Option<MovePathIndex>
-    where F: FnMut(&mir::Projection<'tcx>) -> bool
+    where F: FnMut(&mir::PlaceElem<'tcx>) -> bool
 {
     let mut next_child = move_data.move_paths[path].first_child;
     while let Some(child_index) = next_child {
-        match move_data.move_paths[child_index].place.projection {
-            Some(ref proj) => {
-                if cond(proj) {
-                    return Some(child_index)
-                }
+        let move_path_children = &move_data.move_paths[child_index];
+        if let Some(elem) = move_path_children.place.projection.last() {
+            if cond(elem) {
+                return Some(child_index)
             }
-            _ => {}
         }
-        next_child = move_data.move_paths[child_index].next_sibling;
+        next_child = move_path_children.next_sibling;
     }
 
     None
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
index d94ebdb..1c43a55 100644
--- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs
+++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
@@ -93,19 +93,10 @@
 }
 
 fn find_local(place: &Place<'_>) -> Option<Local> {
-    place.iterate(|place_base, place_projection| {
-        for proj in place_projection {
-            if proj.elem == ProjectionElem::Deref {
-                return None;
-            }
-        }
-
-        if let PlaceBase::Local(local) = place_base {
-            Some(*local)
-        } else {
-            None
-        }
-    })
+    match place.base {
+        PlaceBase::Local(local) if !place.is_indirect() => Some(local),
+        _ => None,
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> {
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 018fd2e..a86fcb3 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -208,7 +208,7 @@
             // If the borrowed place is a local with no projections, all other borrows of this
             // local must conflict. This is purely an optimization so we don't have to call
             // `places_conflict` for every borrow.
-            if place.projection.is_none() {
+            if place.projection.is_empty() {
                 trans.kill_all(other_borrows_of_local);
                 return;
             }
@@ -268,12 +268,8 @@
 
         debug!("Borrows::statement_effect: stmt={:?}", stmt);
         match stmt.kind {
-            mir::StatementKind::Assign(ref lhs, ref rhs) => {
-                // Make sure there are no remaining borrows for variables
-                // that are assigned over.
-                self.kill_borrows_on_place(trans, lhs);
-
-                if let mir::Rvalue::Ref(_, _, ref place) = **rhs {
+            mir::StatementKind::Assign(box(ref lhs, ref rhs)) => {
+                if let mir::Rvalue::Ref(_, _, ref place) = *rhs {
                     if place.ignore_borrow(
                         self.tcx,
                         self.body,
@@ -287,6 +283,10 @@
 
                     trans.gen(*index);
                 }
+
+                // Make sure there are no remaining borrows for variables
+                // that are assigned over.
+                self.kill_borrows_on_place(trans, lhs);
             }
 
             mir::StatementKind::StorageDead(local) => {
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index 0e01701..0f66b13 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -119,8 +119,8 @@
         match stmt.kind {
             StatementKind::StorageLive(l) => sets.gen(l),
             StatementKind::StorageDead(l) => sets.kill(l),
-            StatementKind::Assign(ref place, _)
-            | StatementKind::SetDiscriminant { ref place, .. } => {
+            StatementKind::Assign(box(ref place, _))
+            | StatementKind::SetDiscriminant { box ref place, .. } => {
                 if let PlaceBase::Local(local) = place.base {
                     sets.gen(local);
                 }
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 7fe2a89..319abbb 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -56,7 +56,7 @@
 /// string (as well as that of rendering up-front); in exchange, you
 /// don't have to hand over ownership of your value or deal with
 /// borrowing it.
-pub(crate) struct DebugFormatted(String);
+pub struct DebugFormatted(String);
 
 impl DebugFormatted {
     pub fn new(input: &dyn fmt::Debug) -> DebugFormatted {
@@ -70,7 +70,7 @@
     }
 }
 
-pub(crate) trait Dataflow<'tcx, BD: BitDenotation<'tcx>> {
+pub trait Dataflow<'tcx, BD: BitDenotation<'tcx>> {
     /// Sets up and runs the dataflow problem, using `p` to render results if
     /// implementation so chooses.
     fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> DebugFormatted {
@@ -121,7 +121,7 @@
     pub(crate) param_env: ty::ParamEnv<'tcx>,
 }
 
-pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(
+pub fn do_dataflow<'a, 'tcx, BD, P>(
     tcx: TyCtxt<'tcx>,
     body: &'a Body<'tcx>,
     def_id: DefId,
@@ -453,34 +453,10 @@
     {
         self.flow_state.each_gen_bit(f)
     }
-}
 
-pub fn state_for_location<'tcx, T: BitDenotation<'tcx>>(loc: Location,
-                                                        analysis: &T,
-                                                        result: &DataflowResults<'tcx, T>,
-                                                        body: &Body<'tcx>)
-    -> BitSet<T::Idx> {
-    let mut trans = GenKill::from_elem(HybridBitSet::new_empty(analysis.bits_per_block()));
-
-    for stmt in 0..loc.statement_index {
-        let mut stmt_loc = loc;
-        stmt_loc.statement_index = stmt;
-        analysis.before_statement_effect(&mut trans, stmt_loc);
-        analysis.statement_effect(&mut trans, stmt_loc);
+    pub fn get(&self) -> &BitSet<BD::Idx> {
+        self.flow_state.as_dense()
     }
-
-    // Apply the pre-statement effect of the statement we're evaluating.
-    if loc.statement_index == body[loc.block].statements.len() {
-        analysis.before_terminator_effect(&mut trans, loc);
-    } else {
-        analysis.before_statement_effect(&mut trans, loc);
-    }
-
-    // Apply the transfer function for all preceding statements to the fixpoint
-    // at the start of the block.
-    let mut state = result.sets().entry_set_for(loc.block.index()).to_owned();
-    trans.apply(&mut state);
-    state
 }
 
 pub struct DataflowAnalysis<'a, 'tcx, O>
@@ -565,7 +541,7 @@
     pub(crate) kill_set: T,
 }
 
-type GenKillSet<T> = GenKill<HybridBitSet<T>>;
+pub type GenKillSet<T> = GenKill<HybridBitSet<T>>;
 
 impl<T> GenKill<T> {
     /// Creates a new tuple where `gen_set == kill_set == elem`.
@@ -580,28 +556,28 @@
 }
 
 impl<E:Idx> GenKillSet<E> {
-    pub(crate) fn clear(&mut self) {
+    pub fn clear(&mut self) {
         self.gen_set.clear();
         self.kill_set.clear();
     }
 
-    fn gen(&mut self, e: E) {
+    pub fn gen(&mut self, e: E) {
         self.gen_set.insert(e);
         self.kill_set.remove(e);
     }
 
-    fn gen_all(&mut self, i: impl IntoIterator<Item: Borrow<E>>) {
+    pub fn gen_all(&mut self, i: impl IntoIterator<Item: Borrow<E>>) {
         for j in i {
             self.gen(*j.borrow());
         }
     }
 
-    fn kill(&mut self, e: E) {
+    pub fn kill(&mut self, e: E) {
         self.gen_set.remove(e);
         self.kill_set.insert(e);
     }
 
-    fn kill_all(&mut self, i: impl IntoIterator<Item: Borrow<E>>) {
+    pub fn kill_all(&mut self, i: impl IntoIterator<Item: Borrow<E>>) {
         for j in i {
             self.kill(*j.borrow());
         }
diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
index b26547c..d97f3b7 100644
--- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs
+++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
@@ -11,7 +11,7 @@
 //! `a[x]` would still overlap them both. But that is not this
 //! representation does today.)
 
-use rustc::mir::{Local, PlaceElem, Operand, ProjectionElem};
+use rustc::mir::{Local, Operand, PlaceElem, ProjectionElem};
 use rustc::ty::Ty;
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@@ -26,36 +26,36 @@
 }
 impl<'tcx> Lift for Operand<'tcx> {
     type Abstract = AbstractOperand;
-    fn lift(&self) -> Self::Abstract { AbstractOperand }
+    fn lift(&self) -> Self::Abstract {
+        AbstractOperand
+    }
 }
 impl Lift for Local {
     type Abstract = AbstractOperand;
-    fn lift(&self) -> Self::Abstract { AbstractOperand }
+    fn lift(&self) -> Self::Abstract {
+        AbstractOperand
+    }
 }
 impl<'tcx> Lift for Ty<'tcx> {
     type Abstract = AbstractType;
-    fn lift(&self) -> Self::Abstract { AbstractType }
+    fn lift(&self) -> Self::Abstract {
+        AbstractType
+    }
 }
 impl<'tcx> Lift for PlaceElem<'tcx> {
     type Abstract = AbstractElem;
     fn lift(&self) -> Self::Abstract {
         match *self {
-            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::ConstantIndex {offset,min_length,from_end} =>
-                ProjectionElem::ConstantIndex {
-                    offset,
-                    min_length,
-                    from_end,
-                },
-            ProjectionElem::Downcast(a, u) =>
-                ProjectionElem::Downcast(a, u.clone()),
+            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::ConstantIndex { offset, min_length, from_end } => {
+                ProjectionElem::ConstantIndex { offset, min_length, from_end }
+            }
+            ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a, u.clone()),
         }
     }
 }
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 366b96b..698c501 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -1,16 +1,18 @@
-use rustc::ty::{self, TyCtxt};
-use rustc::mir::*;
 use rustc::mir::tcx::RvalueInitializationState;
-use rustc_data_structures::indexed_vec::{IndexVec};
-use smallvec::{SmallVec, smallvec};
+use rustc::mir::*;
+use rustc::ty::{self, TyCtxt};
+use rustc_data_structures::indexed_vec::IndexVec;
+use smallvec::{smallvec, SmallVec};
 
 use std::collections::hash_map::Entry;
 use std::mem;
 
 use super::abs_domain::Lift;
-use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, MoveOut, MoveOutIndex};
-use super::{MoveError, InitIndex, Init, InitLocation, LookupResult, InitKind};
 use super::IllegalMoveOriginKind::*;
+use super::{Init, InitIndex, InitKind, InitLocation, LookupResult, MoveError};
+use super::{
+    LocationMap, MoveData, MoveOut, MoveOutIndex, MovePath, MovePathIndex, MovePathLookup,
+};
 
 struct MoveDataBuilder<'a, 'tcx> {
     body: &'a Body<'tcx>,
@@ -33,15 +35,19 @@
                 moves: IndexVec::new(),
                 loc_map: LocationMap::new(body),
                 rev_lookup: MovePathLookup {
-                    locals: body.local_decls.indices().map(|i| {
-                        Self::new_move_path(
-                            &mut move_paths,
-                            &mut path_map,
-                            &mut init_path_map,
-                            None,
-                            Place::from(i),
-                        )
-                    }).collect(),
+                    locals: body
+                        .local_decls
+                        .indices()
+                        .map(|i| {
+                            Self::new_move_path(
+                                &mut move_paths,
+                                &mut path_map,
+                                &mut init_path_map,
+                                None,
+                                Place::from(i),
+                            )
+                        })
+                        .collect(),
                     projections: Default::default(),
                 },
                 move_paths,
@@ -49,27 +55,22 @@
                 inits: IndexVec::new(),
                 init_loc_map: LocationMap::new(body),
                 init_path_map,
-            }
+            },
         }
     }
 
-    fn new_move_path(move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>,
-                     path_map: &mut IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
-                     init_path_map: &mut IndexVec<MovePathIndex, SmallVec<[InitIndex; 4]>>,
-                     parent: Option<MovePathIndex>,
-                     place: Place<'tcx>)
-                     -> MovePathIndex
-    {
-        let move_path = move_paths.push(MovePath {
-            next_sibling: None,
-            first_child: None,
-            parent,
-            place,
-        });
+    fn new_move_path(
+        move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>,
+        path_map: &mut IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
+        init_path_map: &mut IndexVec<MovePathIndex, SmallVec<[InitIndex; 4]>>,
+        parent: Option<MovePathIndex>,
+        place: Place<'tcx>,
+    ) -> MovePathIndex {
+        let move_path =
+            move_paths.push(MovePath { next_sibling: None, first_child: None, parent, place });
 
         if let Some(parent) = parent {
-            let next_sibling =
-                mem::replace(&mut move_paths[parent].first_child, Some(move_path));
+            let next_sibling = mem::replace(&mut move_paths[parent].first_child, Some(move_path));
             move_paths[move_path].next_sibling = next_sibling;
         }
 
@@ -91,69 +92,76 @@
     /// problematic for borrowck.
     ///
     /// Maybe we should have separate "borrowck" and "moveck" modes.
-    fn move_path_for(&mut self, place: &Place<'tcx>)
-                     -> Result<MovePathIndex, MoveError<'tcx>>
-    {
+    fn move_path_for(&mut self, place: &Place<'tcx>) -> Result<MovePathIndex, MoveError<'tcx>> {
         debug!("lookup({:?})", place);
-        place.iterate(|place_base, place_projection| {
-            let mut base = match place_base {
-                PlaceBase::Local(local) => self.builder.data.rev_lookup.locals[*local],
-                PlaceBase::Static(..) => {
-                    return Err(MoveError::cannot_move_out_of(self.loc, Static));
+        let mut base = match place.base {
+            PlaceBase::Local(local) => self.builder.data.rev_lookup.locals[local],
+            PlaceBase::Static(..) => {
+                return Err(MoveError::cannot_move_out_of(self.loc, Static));
+            }
+        };
+
+        for (i, elem) in place.projection.iter().enumerate() {
+            let proj_base = &place.projection[..i];
+            let body = self.builder.body;
+            let tcx = self.builder.tcx;
+            let place_ty = Place::ty_from(&place.base, proj_base, body, tcx).ty;
+            match place_ty.sty {
+                ty::Ref(..) | ty::RawPtr(..) => {
+                    let proj = &place.projection[..i+1];
+                    return Err(MoveError::cannot_move_out_of(
+                        self.loc,
+                        BorrowedContent {
+                            target_place: Place {
+                                base: place.base.clone(),
+                                projection: proj.to_vec().into_boxed_slice(),
+                            },
+                        },
+                    ));
                 }
+                ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => {
+                    return Err(MoveError::cannot_move_out_of(
+                        self.loc,
+                        InteriorOfTypeWithDestructor { container_ty: place_ty },
+                    ));
+                }
+                // move out of union - always move the entire union
+                ty::Adt(adt, _) if adt.is_union() => {
+                    return Err(MoveError::UnionMove { path: base });
+                }
+                ty::Slice(_) => {
+                    return Err(MoveError::cannot_move_out_of(
+                        self.loc,
+                        InteriorOfSliceOrArray {
+                            ty: place_ty,
+                            is_index: match elem {
+                                ProjectionElem::Index(..) => true,
+                                _ => false,
+                            },
+                        },
+                    ));
+                }
+                ty::Array(..) => match elem {
+                    ProjectionElem::Index(..) => {
+                        return Err(MoveError::cannot_move_out_of(
+                            self.loc,
+                            InteriorOfSliceOrArray { ty: place_ty, is_index: true },
+                        ));
+                    }
+                    _ => {
+                        // FIXME: still badly broken
+                    }
+                },
+                _ => {}
             };
 
-            for proj in place_projection {
-                let body = self.builder.body;
-                let tcx = self.builder.tcx;
-                let place_ty = Place::ty_from(place_base, &proj.base, body, tcx).ty;
-                match place_ty.sty {
-                    ty::Ref(..) | ty::RawPtr(..) =>
-                        return Err(MoveError::cannot_move_out_of(
-                            self.loc,
-                            BorrowedContent {
-                                target_place: Place {
-                                    base: place_base.clone(),
-                                    projection: Some(Box::new(proj.clone())),
-                                }
-                            })),
-                    ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() =>
-                        return Err(MoveError::cannot_move_out_of(self.loc,
-                                                                 InteriorOfTypeWithDestructor {
-                            container_ty: place_ty
-                        })),
-                    // move out of union - always move the entire union
-                    ty::Adt(adt, _) if adt.is_union() =>
-                        return Err(MoveError::UnionMove { path: base }),
-                    ty::Slice(_) =>
-                        return Err(MoveError::cannot_move_out_of(
-                            self.loc,
-                            InteriorOfSliceOrArray {
-                                ty: place_ty, is_index: match proj.elem {
-                                    ProjectionElem::Index(..) => true,
-                                    _ => false
-                                },
-                            })),
-                    ty::Array(..) => match proj.elem {
-                        ProjectionElem::Index(..) =>
-                            return Err(MoveError::cannot_move_out_of(
-                                self.loc,
-                                InteriorOfSliceOrArray {
-                                    ty: place_ty, is_index: true
-                                })),
-                        _ => {
-                            // FIXME: still badly broken
-                        }
-                    },
-                    _ => {}
-                };
-
-                base = match self
-                    .builder
-                    .data
-                    .rev_lookup
-                    .projections
-                    .entry((base, proj.elem.lift()))
+            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) => {
@@ -163,18 +171,17 @@
                             &mut self.builder.data.init_path_map,
                             Some(base),
                             Place {
-                                base: place_base.clone(),
-                                projection: Some(Box::new(proj.clone())),
+                                base: place.base.clone(),
+                                projection: proj.to_vec().into_boxed_slice(),
                             },
                         );
                         ent.insert(path);
                         path
                     }
                 };
-            }
+        }
 
-            Ok(base)
-        })
+        Ok(base)
     }
 
     fn create_move_path(&mut self, place: &Place<'tcx>) {
@@ -186,7 +193,7 @@
 
 impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
     fn finalize(
-        self
+        self,
     ) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
         debug!("{}", {
             debug!("moves for {:?}:", self.body.span);
@@ -200,11 +207,7 @@
             "done dumping moves"
         });
 
-        if !self.errors.is_empty() {
-            Err((self.data, self.errors))
-        } else {
-            Ok(self.data)
-        }
+        if !self.errors.is_empty() { Err((self.data, self.errors)) } else { Ok(self.data) }
     }
 }
 
@@ -222,10 +225,7 @@
             builder.gather_statement(source, stmt);
         }
 
-        let terminator_loc = Location {
-            block: bb,
-            statement_index: block.statements.len()
-        };
+        let terminator_loc = Location { block: bb, statement_index: block.statements.len() };
         builder.gather_terminator(terminator_loc, block.terminator());
     }
 
@@ -238,11 +238,12 @@
             let path = self.data.rev_lookup.locals[arg];
 
             let init = self.data.inits.push(Init {
-                path, kind: InitKind::Deep, location: InitLocation::Argument(arg),
+                path,
+                kind: InitKind::Deep,
+                location: InitLocation::Argument(arg),
             });
 
-            debug!("gather_args: adding init {:?} of {:?} for argument {:?}",
-                init, path, arg);
+            debug!("gather_args: adding init {:?} of {:?} for argument {:?}", init, path, arg);
 
             self.data.init_path_map[path].push(init);
         }
@@ -267,7 +268,7 @@
 impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
     fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
         match stmt.kind {
-            StatementKind::Assign(ref place, ref rval) => {
+            StatementKind::Assign(box(ref place, ref rval)) => {
                 self.create_move_path(place);
                 if let RvalueInitializationState::Shallow = rval.initialization_state() {
                     // Box starts out uninitialized - need to create a separate
@@ -297,26 +298,26 @@
             StatementKind::StorageDead(local) => {
                 self.gather_move(&Place::from(local));
             }
-            StatementKind::SetDiscriminant{ .. } => {
-                span_bug!(stmt.source_info.span,
-                          "SetDiscriminant should not exist during borrowck");
+            StatementKind::SetDiscriminant { .. } => {
+                span_bug!(
+                    stmt.source_info.span,
+                    "SetDiscriminant should not exist during borrowck"
+                );
             }
-            StatementKind::Retag { .. } |
-            StatementKind::AscribeUserType(..) |
-            StatementKind::Nop => {}
+            StatementKind::Retag { .. }
+            | StatementKind::AscribeUserType(..)
+            | StatementKind::Nop => {}
         }
     }
 
     fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
         match *rvalue {
-            Rvalue::Use(ref operand) |
-            Rvalue::Repeat(ref operand, _) |
-            Rvalue::Cast(_, ref operand, _) |
-            Rvalue::UnaryOp(_, ref operand) => {
-                self.gather_operand(operand)
-            }
-            Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) |
-            Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => {
+            Rvalue::Use(ref operand)
+            | Rvalue::Repeat(ref operand, _)
+            | Rvalue::Cast(_, ref operand, _)
+            | Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand),
+            Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs)
+            | Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => {
                 self.gather_operand(lhs);
                 self.gather_operand(rhs);
             }
@@ -325,11 +326,11 @@
                     self.gather_operand(operand);
                 }
             }
-            Rvalue::Ref(..) |
-            Rvalue::Discriminant(..) |
-            Rvalue::Len(..) |
-            Rvalue::NullaryOp(NullOp::SizeOf, _) |
-            Rvalue::NullaryOp(NullOp::Box, _) => {
+            Rvalue::Ref(..)
+            | Rvalue::Discriminant(..)
+            | Rvalue::Len(..)
+            | Rvalue::NullaryOp(NullOp::SizeOf, _)
+            | Rvalue::NullaryOp(NullOp::Box, _) => {
                 // This returns an rvalue with uninitialized contents. We can't
                 // move out of it here because it is an rvalue - assignments always
                 // completely initialize their place.
@@ -346,16 +347,16 @@
 
     fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
         match term.kind {
-            TerminatorKind::Goto { target: _ } |
-            TerminatorKind::Resume |
-            TerminatorKind::Abort |
-            TerminatorKind::GeneratorDrop |
-            TerminatorKind::FalseEdges { .. } |
-            TerminatorKind::FalseUnwind { .. } |
-            TerminatorKind::Unreachable => { }
+            TerminatorKind::Goto { target: _ }
+            | TerminatorKind::Resume
+            | TerminatorKind::Abort
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseUnwind { .. }
+            | TerminatorKind::Unreachable => {}
 
             TerminatorKind::Return => {
-                self.gather_move(&Place::RETURN_PLACE);
+                self.gather_move(&Place::return_place());
             }
 
             TerminatorKind::Assert { ref cond, .. } => {
@@ -399,9 +400,9 @@
 
     fn gather_operand(&mut self, operand: &Operand<'tcx>) {
         match *operand {
-            Operand::Constant(..) |
-            Operand::Copy(..) => {} // not-a-move
-            Operand::Move(ref place) => { // a move
+            Operand::Constant(..) | Operand::Copy(..) => {} // not-a-move
+            Operand::Move(ref place) => {
+                // a move
                 self.gather_move(place);
             }
         }
@@ -419,8 +420,10 @@
         };
         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);
+        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);
@@ -433,9 +436,7 @@
 
         // Check if we are assigning into a field of a union, if so, lookup the place
         // of the union so it is marked as initialized again.
-        if let Some(box Projection { base: proj_base, elem: ProjectionElem::Field(_, _) }) =
-            place.projection
-        {
+        if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection {
             if let ty::Adt(def, _) =
                 Place::ty_from(place.base, proj_base, self.builder.body, self.builder.tcx).ty.sty
             {
@@ -452,8 +453,10 @@
                 kind,
             });
 
-            debug!("gather_init({:?}, {:?}): adding init {:?} of {:?}",
-               self.loc, place, init, path);
+            debug!(
+                "gather_init({:?}, {:?}): adding init {:?} of {:?}",
+                self.loc, place, init, path
+            );
 
             self.builder.data.init_path_map[path].push(init);
             self.builder.data.init_loc_map[self.loc].push(init);
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index e5a1957..156c19c 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -1,9 +1,10 @@
-use rustc::ty::{Ty, TyCtxt};
+use core::slice::Iter;
 use rustc::mir::*;
+use rustc::ty::{Ty, TyCtxt};
 use rustc::util::nodemap::FxHashMap;
-use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::indexed_vec::{Enumerated, Idx, IndexVec};
 use smallvec::SmallVec;
-use syntax_pos::{Span};
+use syntax_pos::Span;
 
 use std::fmt;
 use std::ops::{Index, IndexMut};
@@ -137,12 +138,17 @@
     }
 }
 
-impl<T> LocationMap<T> where T: Default + Clone {
+impl<T> LocationMap<T>
+where
+    T: Default + Clone,
+{
     fn new(body: &Body<'_>) -> Self {
         LocationMap {
-            map: body.basic_blocks().iter().map(|block| {
-                vec![T::default(); block.statements.len()+1]
-            }).collect()
+            map: body
+                .basic_blocks()
+                .iter()
+                .map(|block| vec![T::default(); block.statements.len() + 1])
+                .collect(),
         }
     }
 }
@@ -178,7 +184,6 @@
     pub kind: InitKind,
 }
 
-
 /// Initializations can be from an argument or from a statement. Arguments
 /// do not have locations, in those cases the `Local` is kept..
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -224,7 +229,7 @@
     /// subsequent search so that it is solely relative to that
     /// base-place). For the remaining lookup, we map the projection
     /// elem to the associated MovePathIndex.
-    projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>
+    projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>,
 }
 
 mod builder;
@@ -232,7 +237,7 @@
 #[derive(Copy, Clone, Debug)]
 pub enum LookupResult {
     Exact(MovePathIndex),
-    Parent(Option<MovePathIndex>)
+    Parent(Option<MovePathIndex>),
 }
 
 impl MovePathLookup {
@@ -240,28 +245,32 @@
     // alternative will *not* create a MovePath on the fly for an
     // unknown place, but will rather return the nearest available
     // parent.
-    pub fn find(&self, place_ref: PlaceRef<'_, '_>) -> LookupResult {
-        place_ref.iterate(|place_base, place_projection| {
-            let mut result = match place_base {
-                PlaceBase::Local(local) => self.locals[*local],
-                PlaceBase::Static(..) => return LookupResult::Parent(None),
-            };
+    pub fn find(&self, place: PlaceRef<'_, '_>) -> LookupResult {
+        let mut result = match place.base {
+            PlaceBase::Local(local) => self.locals[*local],
+            PlaceBase::Static(..) => return LookupResult::Parent(None),
+        };
 
-            for proj in place_projection {
-                if let Some(&subpath) = self.projections.get(&(result, proj.elem.lift())) {
-                    result = subpath;
-                } else {
-                    return LookupResult::Parent(Some(result));
-                }
+        for elem in place.projection.iter() {
+            if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
+                result = subpath;
+            } else {
+                return LookupResult::Parent(Some(result));
             }
+        }
 
-            LookupResult::Exact(result)
-        })
+        LookupResult::Exact(result)
     }
 
     pub fn find_local(&self, local: Local) -> MovePathIndex {
         self.locals[local]
     }
+
+    /// An enumerated iterator of `local`s and their associated
+    /// `MovePathIndex`es.
+    pub fn iter_locals_enumerated(&self) -> Enumerated<Local, Iter<'_, MovePathIndex>> {
+        self.locals.iter_enumerated()
+    }
 }
 
 #[derive(Debug)]
@@ -289,7 +298,7 @@
     InteriorOfTypeWithDestructor { container_ty: Ty<'tcx> },
 
     /// Illegal move due to attempt to move out of a slice or array.
-    InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool, },
+    InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool },
 }
 
 #[derive(Debug)]
@@ -318,11 +327,15 @@
     pub fn base_local(&self, mut mpi: MovePathIndex) -> Option<Local> {
         loop {
             let path = &self.move_paths[mpi];
-            if let Place {
-                base: PlaceBase::Local(l),
-                projection: None,
-            } = path.place { return Some(l); }
-            if let Some(parent) = path.parent { mpi = parent; continue } else { return None }
+            if let Place { base: PlaceBase::Local(l), projection: box [] } = path.place {
+                return Some(l);
+            }
+            if let Some(parent) = path.parent {
+                mpi = parent;
+                continue;
+            } else {
+                return None;
+            }
         }
     }
 }
diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs
index 86c263a..ba299e9 100644
--- a/src/librustc_mir/error_codes.rs
+++ b/src/librustc_mir/error_codes.rs
@@ -1,4 +1,4 @@
-register_long_diagnostics! {
+syntax::register_diagnostics! {
 
 
 E0001: r##"
@@ -157,81 +157,6 @@
 See also the error E0303.
 "##,
 
-E0008: r##"
-Names bound in match arms retain their type in pattern guards. As such, if a
-name is bound by move in a pattern, it should also be moved to wherever it is
-referenced in the pattern guard code. Doing so however would prevent the name
-from being available in the body of the match arm. Consider the following:
-
-```compile_fail,E0008
-match Some("hi".to_string()) {
-    Some(s) if s.len() == 0 => {}, // use s.
-    _ => {},
-}
-```
-
-The variable `s` has type `String`, and its use in the guard is as a variable of
-type `String`. The guard code effectively executes in a separate scope to the
-body of the arm, so the value would be moved into this anonymous scope and
-therefore becomes unavailable in the body of the arm.
-
-The problem above can be solved by using the `ref` keyword.
-
-```
-match Some("hi".to_string()) {
-    Some(ref s) if s.len() == 0 => {},
-    _ => {},
-}
-```
-
-Though this example seems innocuous and easy to solve, the problem becomes clear
-when it encounters functions which consume the value:
-
-```compile_fail,E0008
-struct A{}
-
-impl A {
-    fn consume(self) -> usize {
-        0
-    }
-}
-
-fn main() {
-    let a = Some(A{});
-    match a {
-        Some(y) if y.consume() > 0 => {}
-        _ => {}
-    }
-}
-```
-
-In this situation, even the `ref` keyword cannot solve it, since borrowed
-content cannot be moved. This problem cannot be solved generally. If the value
-can be cloned, here is a not-so-specific solution:
-
-```
-#[derive(Clone)]
-struct A{}
-
-impl A {
-    fn consume(self) -> usize {
-        0
-    }
-}
-
-fn main() {
-    let a = Some(A{});
-    match a{
-        Some(ref y) if y.clone().consume() > 0 => {}
-        _ => {}
-    }
-}
-```
-
-If the value will be consumed in the pattern guard, using its clone will not
-move its ownership, so the code works.
-"##,
-
 E0009: r##"
 In a pattern, all values that don't implement the `Copy` trait have to be bound
 the same way. The goal here is to avoid binding simultaneously by-move and
@@ -475,13 +400,15 @@
 "##,
 
 E0301: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 Mutable borrows are not allowed in pattern guards, because matching cannot have
 side effects. Side effects could alter the matched object or the environment
 on which the match depends in such a way, that the match would not be
 exhaustive. For instance, the following would not match any arm if mutable
 borrows were allowed:
 
-```compile_fail,E0301
+```compile_fail,E0596
 match Some(()) {
     None => { },
     option if option.take().is_none() => {
@@ -493,13 +420,15 @@
 "##,
 
 E0302: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 Assignments are not allowed in pattern guards, because matching cannot have
 side effects. Side effects could alter the matched object or the environment
 on which the match depends in such a way, that the match would not be
 exhaustive. For instance, the following would not match any arm if assignments
 were allowed:
 
-```compile_fail,E0302
+```compile_fail,E0594
 match Some(()) {
     None => { },
     option if { option = None; false } => { },
@@ -748,7 +677,7 @@
 ```compile_fail,E0381
 fn main() {
     let x: i32;
-    let y = x; // error, use of possibly uninitialized variable
+    let y = x; // error, use of possibly-uninitialized variable
 }
 ```
 
@@ -1717,7 +1646,14 @@
 "##,
 
 E0507: r##"
-You tried to move out of a value which was borrowed. Erroneous code example:
+You tried to move out of a value which was borrowed.
+
+This can also happen when using a type implementing `Fn` or `FnMut`, as neither
+allows moving out of them (they usually represent closures which can be called
+more than once). Much of the text following applies equally well to non-`FnOnce`
+closure bodies.
+
+Erroneous code example:
 
 ```compile_fail,E0507
 use std::cell::RefCell;
@@ -1989,7 +1925,6 @@
 could cause the match to be non-exhaustive:
 
 ```compile_fail,E0510
-#![feature(bind_by_move_pattern_guards)]
 let mut x = Some(0);
 match x {
     None => (),
@@ -2448,9 +2383,10 @@
 
 There are some known bugs that trigger this message.
 "##,
-}
 
-register_diagnostics! {
+;
+
+//  E0008, // cannot bind by-move into a pattern guard
 //  E0298, // cannot compare constants
 //  E0299, // mismatched types between arms
 //  E0471, // constant evaluation error (in pattern)
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 222750e..a6d955f 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -517,9 +517,9 @@
 pub struct Witness<'tcx>(Vec<Pattern<'tcx>>);
 
 impl<'tcx> Witness<'tcx> {
-    pub fn single_pattern(&self) -> &Pattern<'tcx> {
+    pub fn single_pattern(self) -> Pattern<'tcx> {
         assert_eq!(self.0.len(), 1);
-        &self.0[0]
+        self.0.into_iter().next().unwrap()
     }
 
     fn push_wild_constructor<'a>(
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 5352888..161c58a 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -5,11 +5,6 @@
 use super::{Pattern, PatternContext, PatternError, PatternKind};
 
 use rustc::middle::borrowck::SignalledError;
-use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
-use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
-use rustc::middle::expr_use_visitor as euv;
-use rustc::middle::mem_categorization::cmt_;
-use rustc::middle::region;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
@@ -36,9 +31,7 @@
 
     let mut visitor = MatchVisitor {
         tcx,
-        body_owner: def_id,
         tables: tcx.body_tables(body_id),
-        region_scope_tree: &tcx.region_scope_tree(def_id),
         param_env: tcx.param_env(def_id),
         identity_substs: InternalSubsts::identity_for_item(tcx, def_id),
         signalled_error: SignalledError::NoErrorsSeen,
@@ -53,15 +46,13 @@
 
 struct MatchVisitor<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    body_owner: DefId,
     tables: &'a ty::TypeckTables<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     identity_substs: SubstsRef<'tcx>,
-    region_scope_tree: &'a region::ScopeTree,
     signalled_error: SignalledError,
 }
 
-impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
+impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
         NestedVisitorMap::None
     }
@@ -98,8 +89,7 @@
     }
 }
 
-
-impl<'a, 'tcx> PatternContext<'a, 'tcx> {
+impl PatternContext<'_, '_> {
     fn report_inlining_errors(&self, pat_span: Span) {
         for error in &self.errors {
             match *error {
@@ -131,7 +121,7 @@
     }
 }
 
-impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
+impl<'tcx> MatchVisitor<'_, 'tcx> {
     fn check_patterns(&mut self, has_guard: bool, pats: &[P<Pat>]) {
         check_legality_of_move_bindings(self, has_guard, pats);
         for pat in pats {
@@ -151,11 +141,8 @@
 
             // Second, if there is a guard on each arm, make sure it isn't
             // assigning or borrowing anything mutably.
-            if let Some(ref guard) = arm.guard {
+            if arm.guard.is_some() {
                 self.signalled_error = SignalledError::SawSomeError;
-                if !self.tcx.features().bind_by_move_pattern_guards {
-                    check_for_mutation_in_guard(self, &guard);
-                }
             }
 
             // Third, perform some lints.
@@ -277,37 +264,26 @@
                 expand_pattern(cx, pattern)
             ]].into_iter().collect();
 
-            let wild_pattern = Pattern {
-                ty: pattern_ty,
-                span: DUMMY_SP,
-                kind: box PatternKind::Wild,
-            };
-            let witness = match is_useful(cx, &pats, &[&wild_pattern], ConstructWitness) {
-                UsefulWithWitness(witness) => witness,
-                NotUseful => return,
-                Useful => bug!()
+            let witnesses = match check_not_useful(cx, pattern_ty, &pats) {
+                Ok(_) => return,
+                Err(err) => err,
             };
 
-            let pattern_string = witness[0].single_pattern().to_string();
+            let joined_patterns = joined_uncovered_patterns(&witnesses);
             let mut err = struct_span_err!(
                 self.tcx.sess, pat.span, E0005,
-                "refutable pattern in {}: `{}` not covered",
-                origin, pattern_string
+                "refutable pattern in {}: {} not covered",
+                origin, joined_patterns
             );
-            let label_msg = match pat.node {
-                PatKind::Path(hir::QPath::Resolved(None, ref path))
-                        if path.segments.len() == 1 && path.segments[0].args.is_none() => {
+            err.span_label(pat.span, match &pat.node {
+                PatKind::Path(hir::QPath::Resolved(None, path))
+                    if path.segments.len() == 1 && path.segments[0].args.is_none() => {
                     format!("interpreted as {} {} pattern, not new variable",
                             path.res.article(), path.res.descr())
                 }
-                _ => format!("pattern `{}` not covered", pattern_string),
-            };
-            err.span_label(pat.span, label_msg);
-            if let ty::Adt(def, _) = pattern_ty.sty {
-                if let Some(sp) = self.tcx.hir().span_if_local(def.did){
-                    err.span_label(sp, format!("`{}` defined here", pattern_ty));
-                }
-            }
+                _ => pattern_not_convered_label(&witnesses, &joined_patterns),
+            });
+            adt_defined_here(cx, &mut err, pattern_ty, &witnesses);
             err.emit();
         });
     }
@@ -362,9 +338,9 @@
 }
 
 // Check for unreachable patterns
-fn check_arms<'a, 'tcx>(
-    cx: &mut MatchCheckCtxt<'a, 'tcx>,
-    arms: &[(Vec<(&'a Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
+fn check_arms<'tcx>(
+    cx: &mut MatchCheckCtxt<'_, 'tcx>,
+    arms: &[(Vec<(&Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
     source: hir::MatchSource,
 ) {
     let mut seen = Matrix::empty();
@@ -445,104 +421,124 @@
     }
 }
 
-fn check_exhaustive<'p, 'a, 'tcx>(
-    cx: &mut MatchCheckCtxt<'a, 'tcx>,
-    scrut_ty: Ty<'tcx>,
-    sp: Span,
-    matrix: &Matrix<'p, 'tcx>,
-) {
-    let wild_pattern = Pattern {
-        ty: scrut_ty,
-        span: DUMMY_SP,
-        kind: box PatternKind::Wild,
-    };
+fn check_not_useful(
+    cx: &mut MatchCheckCtxt<'_, 'tcx>,
+    ty: Ty<'tcx>,
+    matrix: &Matrix<'_, 'tcx>,
+) -> Result<(), Vec<Pattern<'tcx>>> {
+    let wild_pattern = Pattern { ty, span: DUMMY_SP, kind: box PatternKind::Wild };
     match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) {
-        UsefulWithWitness(pats) => {
-            let witnesses = if pats.is_empty() {
-                vec![&wild_pattern]
-            } else {
-                pats.iter().map(|w| w.single_pattern()).collect()
-            };
-
-            const LIMIT: usize = 3;
-            let joined_patterns = match witnesses.len() {
-                0 => bug!(),
-                1 => format!("`{}`", witnesses[0]),
-                2..=LIMIT => {
-                    let (tail, head) = witnesses.split_last().unwrap();
-                    let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
-                    format!("`{}` and `{}`", head.join("`, `"), tail)
-                }
-                _ => {
-                    let (head, tail) = witnesses.split_at(LIMIT);
-                    let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
-                    format!("`{}` and {} more", head.join("`, `"), tail.len())
-                }
-            };
-
-            let label_text = match witnesses.len() {
-                1 => format!("pattern {} not covered", joined_patterns),
-                _ => format!("patterns {} not covered", joined_patterns),
-            };
-            let mut err = create_e0004(cx.tcx.sess, sp, format!(
-                "non-exhaustive patterns: {} not covered",
-                joined_patterns,
-            ));
-            err.span_label(sp, label_text);
-            // point at the definition of non-covered enum variants
-            if let ty::Adt(def, _) = scrut_ty.sty {
-                if let Some(sp) = cx.tcx.hir().span_if_local(def.did){
-                    err.span_label(sp, format!("`{}` defined here", scrut_ty));
-                }
-            }
-            let patterns = witnesses.iter().map(|p| (**p).clone()).collect::<Vec<Pattern<'_>>>();
-            if patterns.len() < 4 {
-                for sp in maybe_point_at_variant(cx, scrut_ty, patterns.as_slice()) {
-                    err.span_label(sp, "not covered");
-                }
-            }
-            err.help("ensure that all possible cases are being handled, \
-                      possibly by adding wildcards or more match arms");
-            err.emit();
-        }
-        NotUseful => {
-            // This is good, wildcard pattern isn't reachable
-        }
-        _ => bug!()
+        NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
+        UsefulWithWitness(pats) => Err(if pats.is_empty() {
+            vec![wild_pattern]
+        } else {
+            pats.into_iter().map(|w| w.single_pattern()).collect()
+        }),
+        Useful => bug!(),
     }
 }
 
-fn maybe_point_at_variant(
-    cx: &mut MatchCheckCtxt<'a, 'tcx>,
-    ty: Ty<'tcx>,
-    patterns: &[Pattern<'_>],
-) -> Vec<Span> {
+fn check_exhaustive<'tcx>(
+    cx: &mut MatchCheckCtxt<'_, 'tcx>,
+    scrut_ty: Ty<'tcx>,
+    sp: Span,
+    matrix: &Matrix<'_, 'tcx>,
+) {
+    let witnesses = match check_not_useful(cx, scrut_ty, matrix) {
+        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_convered_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();
+}
+
+fn joined_uncovered_patterns(witnesses: &[Pattern<'_>]) -> String {
+    const LIMIT: usize = 3;
+    match witnesses {
+        [] => bug!(),
+        [witness] => format!("`{}`", witness),
+        [head @ .., tail] if head.len() < LIMIT => {
+            let head: Vec<_> = head.iter().map(<_>::to_string).collect();
+            format!("`{}` and `{}`", head.join("`, `"), tail)
+        }
+        _ => {
+            let (head, tail) = witnesses.split_at(LIMIT);
+            let head: Vec<_> = head.iter().map(<_>::to_string).collect();
+            format!("`{}` and {} more", head.join("`, `"), tail.len())
+        }
+    }
+}
+
+fn pattern_not_convered_label(witnesses: &[Pattern<'_>], joined_patterns: &str) -> String {
+    format!("pattern{} {} not covered", rustc_errors::pluralise!(witnesses.len()), joined_patterns)
+}
+
+/// Point at the definition of non-covered `enum` variants.
+fn adt_defined_here(
+    cx: &MatchCheckCtxt<'_, '_>,
+    err: &mut DiagnosticBuilder<'_>,
+    ty: Ty<'_>,
+    witnesses: &[Pattern<'_>],
+) {
+    let ty = ty.peel_refs();
+    if let ty::Adt(def, _) = ty.sty {
+        if let Some(sp) = cx.tcx.hir().span_if_local(def.did) {
+            err.span_label(sp, format!("`{}` defined here", ty));
+        }
+
+        if witnesses.len() < 4 {
+            for sp in maybe_point_at_variant(ty, &witnesses) {
+                err.span_label(sp, "not covered");
+            }
+        }
+    }
+}
+
+fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[Pattern<'_>]) -> Vec<Span> {
     let mut covered = vec![];
     if let ty::Adt(def, _) = ty.sty {
         // Don't point at variants that have already been covered due to other patterns to avoid
-        // visual clutter
+        // visual clutter.
         for pattern in patterns {
-            let pk: &PatternKind<'_> = &pattern.kind;
-            if let PatternKind::Variant { adt_def, variant_index, subpatterns, .. } = pk {
-                if adt_def.did == def.did {
+            use PatternKind::{AscribeUserType, Deref, Variant, Or, Leaf};
+            match &*pattern.kind {
+                AscribeUserType { subpattern, .. } | Deref { subpattern } => {
+                    covered.extend(maybe_point_at_variant(ty, slice::from_ref(&subpattern)));
+                }
+                Variant { adt_def, variant_index, subpatterns, .. } if adt_def.did == def.did => {
                     let sp = def.variants[*variant_index].ident.span;
                     if covered.contains(&sp) {
                         continue;
                     }
                     covered.push(sp);
-                    let subpatterns = subpatterns.iter()
+
+                    let pats = subpatterns.iter()
                         .map(|field_pattern| field_pattern.pattern.clone())
-                        .collect::<Vec<_>>();
-                    covered.extend(
-                        maybe_point_at_variant(cx, ty, subpatterns.as_slice()),
-                    );
+                        .collect::<Box<[_]>>();
+                    covered.extend(maybe_point_at_variant(ty, &pats));
                 }
-            }
-            if let PatternKind::Leaf { subpatterns } = pk {
-                let subpatterns = subpatterns.iter()
-                    .map(|field_pattern| field_pattern.pattern.clone())
-                    .collect::<Vec<_>>();
-                covered.extend(maybe_point_at_variant(cx, ty, subpatterns.as_slice()));
+                Leaf { subpatterns } => {
+                    let pats = subpatterns.iter()
+                        .map(|field_pattern| field_pattern.pattern.clone())
+                        .collect::<Box<[_]>>();
+                    covered.extend(maybe_point_at_variant(ty, &pats));
+                }
+                Or { pats } => {
+                    let pats = pats.iter().cloned().collect::<Box<[_]>>();
+                    covered.extend(maybe_point_at_variant(ty, &pats));
+                }
+                _ => {}
             }
         }
     }
@@ -582,19 +578,10 @@
                              "cannot bind by-move with sub-bindings")
                 .span_label(p.span, "binds an already bound by-move value by moving it")
                 .emit();
-        } else if has_guard {
-            if !cx.tcx.features().bind_by_move_pattern_guards {
-                let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008,
-                                            "cannot bind by-move into a pattern guard");
-                err.span_label(p.span, "moves value into pattern guard");
-                if cx.tcx.sess.opts.unstable_features.is_nightly_build() {
-                    err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \
-                            crate attributes to enable");
-                }
-                err.emit();
+        } else if !has_guard {
+            if let Some(_by_ref_span) = by_ref_span {
+                span_vec.push(p.span);
             }
-        } else if let Some(_by_ref_span) = by_ref_span {
-            span_vec.push(p.span);
         }
     };
 
@@ -636,67 +623,6 @@
     }
 }
 
-/// Ensures that a pattern guard doesn't borrow by mutable reference or assign.
-//
-// FIXME: this should be done by borrowck.
-fn check_for_mutation_in_guard(cx: &MatchVisitor<'_, '_>, guard: &hir::Guard) {
-    let mut checker = MutationChecker {
-        cx,
-    };
-    match guard {
-        hir::Guard::If(expr) =>
-            ExprUseVisitor::new(&mut checker,
-                                cx.tcx,
-                                cx.body_owner,
-                                cx.param_env,
-                                cx.region_scope_tree,
-                                cx.tables,
-                                None).walk_expr(expr),
-    };
-}
-
-struct MutationChecker<'a, 'tcx> {
-    cx: &'a MatchVisitor<'a, 'tcx>,
-}
-
-impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> {
-    fn matched_pat(&mut self, _: &Pat, _: &cmt_<'_>, _: euv::MatchMode) {}
-    fn consume(&mut self, _: hir::HirId, _: Span, _: &cmt_<'_>, _: ConsumeMode) {}
-    fn consume_pat(&mut self, _: &Pat, _: &cmt_<'_>, _: ConsumeMode) {}
-    fn borrow(&mut self,
-              _: hir::HirId,
-              span: Span,
-              _: &cmt_<'_>,
-              _: ty::Region<'tcx>,
-              kind:ty:: BorrowKind,
-              _: LoanCause) {
-        match kind {
-            ty::MutBorrow => {
-                let mut err = struct_span_err!(self.cx.tcx.sess, span, E0301,
-                          "cannot mutably borrow in a pattern guard");
-                err.span_label(span, "borrowed mutably in pattern guard");
-                if self.cx.tcx.sess.opts.unstable_features.is_nightly_build() {
-                    err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \
-                              crate attributes to enable");
-                }
-                err.emit();
-            }
-            ty::ImmBorrow | ty::UniqueImmBorrow => {}
-        }
-    }
-    fn decl_without_init(&mut self, _: hir::HirId, _: Span) {}
-    fn mutate(&mut self, _: hir::HirId, span: Span, _: &cmt_<'_>, mode: MutateMode) {
-        match mode {
-            MutateMode::JustWrite | MutateMode::WriteAndRead => {
-                struct_span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard")
-                    .span_label(span, "assignment in pattern guard")
-                    .emit();
-            }
-            MutateMode::Init => {}
-        }
-    }
-}
-
 /// Forbids bindings in `@` patterns. This is necessary for memory safety,
 /// because of the way rvalues are handled in the borrow check. (See issue
 /// #14587.)
@@ -709,7 +635,7 @@
     bindings_allowed: bool
 }
 
-impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> {
+impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
         NestedVisitorMap::None
     }
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 6caccfd..4aaa5e8 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -1229,7 +1229,13 @@
                 ty::RawPtr(..) => {
                     // `#[structural_match]` ignores substructure of
                     // `*const _`/`*mut _`, so skip super_visit_with
-
+                    //
+                    // (But still tell caller to continue search.)
+                    return false;
+                }
+                ty::FnDef(..) | ty::FnPtr(..) => {
+                    // types of formals and return in `fn(_) -> _` are also irrelevant
+                    //
                     // (But still tell caller to continue search.)
                     return false;
                 }
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index ac01d43..78996ed 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -14,7 +14,6 @@
 use rustc::ty::query::TyCtxtAt;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::mir::interpret::{
-    ErrorHandled,
     GlobalId, Scalar, Pointer, FrameInfo, AllocId,
     InterpResult, truncate, sign_extend,
 };
@@ -442,27 +441,30 @@
 
                 // Issue #27023: must add any necessary padding to `size`
                 // (to make it a multiple of `align`) before returning it.
-                //
-                // Namely, the returned size should be, in C notation:
-                //
-                //   `size + ((size & (align-1)) ? align : 0)`
-                //
-                // emulated via the semi-standard fast bit trick:
-                //
-                //   `(size + (align-1)) & -align`
+                let size = size.align_to(align);
 
-                Ok(Some((size.align_to(align), align)))
+                // Check if this brought us over the size limit.
+                if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
+                    throw_ub_format!("wide pointer metadata contains invalid information: \
+                        total size is bigger than largest supported object");
+                }
+                Ok(Some((size, align)))
             }
             ty::Dynamic(..) => {
                 let vtable = metadata.expect("dyn trait fat ptr must have vtable");
-                // the second entry in the vtable is the dynamic size of the object.
+                // Read size and align from vtable (already checks size).
                 Ok(Some(self.read_size_and_align_from_vtable(vtable)?))
             }
 
             ty::Slice(_) | ty::Str => {
                 let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?;
                 let elem = layout.field(self, 0)?;
-                Ok(Some((elem.size * len, elem.align.abi)))
+
+                // Make sure the slice is not too big.
+                let size = elem.size.checked_mul(len, &*self.tcx)
+                    .ok_or_else(|| err_ub_format!("invalid slice: \
+                        total size is bigger than largest supported object"))?;
+                Ok(Some((size, elem.align.abi)))
             }
 
             ty::Foreign(_) => {
@@ -669,14 +671,7 @@
         // Our result will later be validated anyway, and there seems no good reason
         // to have to fail early here.  This is also more consistent with
         // `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
-        let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
-            match err {
-                ErrorHandled::Reported =>
-                    err_inval!(ReferencedConstant),
-                ErrorHandled::TooGeneric =>
-                    err_inval!(TooGeneric),
-            }
-        })?;
+        let val = self.tcx.const_eval_raw(param_env.and(gid))?;
         self.raw_const_to_mplace(val)
     }
 
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 32ba70a..95647ce 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -3,7 +3,7 @@
 //! After a const evaluation has computed a value, before we destroy the const evaluator's session
 //! memory, we need to extract all memory allocations to the global memory pool so they stay around.
 
-use rustc::ty::{Ty, TyCtxt, ParamEnv, self};
+use rustc::ty::{Ty, self};
 use rustc::mir::interpret::{InterpResult, ErrorHandled};
 use rustc::hir;
 use rustc::hir::def_id::DefId;
@@ -11,32 +11,29 @@
 use rustc_data_structures::fx::FxHashSet;
 
 use syntax::ast::Mutability;
-use syntax_pos::Span;
 
 use super::{
-    ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, Scalar,
+    ValueVisitor, MemoryKind, AllocId, MPlaceTy, Scalar,
 };
 use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};
 
 struct InternVisitor<'rt, 'mir, 'tcx> {
-    /// previously encountered safe references
-    ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
+    /// The ectx from which we intern.
     ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
-    param_env: ParamEnv<'tcx>,
+    /// Previously encountered safe references.
+    ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
+    /// A list of all encountered allocations. After type-based interning, we traverse this list to
+    /// also intern allocations that are only referenced by a raw pointer or inside a union.
+    leftover_allocations: &'rt mut FxHashSet<AllocId>,
     /// The root node of the value that we're looking at. This field is never mutated and only used
     /// for sanity assertions that will ICE when `const_qualif` screws up.
     mode: InternMode,
     /// This field stores the mutability of the value *currently* being checked.
-    /// It is set to mutable when an `UnsafeCell` is encountered
-    /// When recursing across a reference, we don't recurse but store the
-    /// value to be checked in `ref_tracking` together with the mutability at which we are checking
-    /// the value.
-    /// When encountering an immutable reference, we treat everything as immutable that is behind
-    /// it.
+    /// When encountering a mutable reference, we determine the pointee mutability
+    /// taking into account the mutability of the context: `& &mut i32` is entirely immutable,
+    /// despite the nested mutable reference!
+    /// The field gets updated when an `UnsafeCell` is encountered.
     mutability: Mutability,
-    /// A list of all encountered relocations. After type-based interning, we traverse this list to
-    /// also intern allocations that are only referenced by a raw pointer or inside a union.
-    leftover_relocations: &'rt mut FxHashSet<AllocId>,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
@@ -45,9 +42,10 @@
     /// `static`. In a `static mut` we start out as mutable and thus can also contain further `&mut`
     /// that will actually be treated as mutable.
     Static,
-    /// UnsafeCell is OK in the value of a constant, but not behind references in a constant
+    /// UnsafeCell is OK in the value of a constant: `const FOO = Cell::new(0)` creates
+    /// a new cell every time it is used.
     ConstBase,
-    /// `UnsafeCell` ICEs
+    /// `UnsafeCell` ICEs.
     Const,
 }
 
@@ -55,48 +53,100 @@
 /// into the memory of other constants or statics
 struct IsStaticOrFn;
 
+/// Intern an allocation without looking at its children.
+/// `mode` is the mode of the environment where we found this pointer.
+/// `mutablity` is the mutability of the place to be interned; even if that says
+/// `immutable` things might become mutable if `ty` is not frozen.
+/// `ty` can be `None` if there is no potential interior mutability
+/// to account for (e.g. for vtables).
+fn intern_shallow<'rt, 'mir, 'tcx>(
+    ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
+    leftover_allocations: &'rt mut FxHashSet<AllocId>,
+    mode: InternMode,
+    alloc_id: AllocId,
+    mutability: Mutability,
+    ty: Option<Ty<'tcx>>,
+) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
+    trace!(
+        "InternVisitor::intern {:?} with {:?}",
+        alloc_id, mutability,
+    );
+    // remove allocation
+    let tcx = ecx.tcx;
+    let memory = ecx.memory_mut();
+    let (kind, mut alloc) = match memory.alloc_map.remove(&alloc_id) {
+        Some(entry) => entry,
+        None => {
+            // Pointer not found in local memory map. It is either a pointer to the global
+            // map, or dangling.
+            // If the pointer is dangling (neither in local nor global memory), we leave it
+            // to validation to error. The `delay_span_bug` ensures that we don't forget such
+            // a check in validation.
+            if tcx.alloc_map.lock().get(alloc_id).is_none() {
+                tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer");
+            }
+            // treat dangling pointers like other statics
+            // just to stop trying to recurse into them
+            return Ok(Some(IsStaticOrFn));
+        },
+    };
+    // This match is just a canary for future changes to `MemoryKind`, which most likely need
+    // changes in this function.
+    match kind {
+        MemoryKind::Stack | MemoryKind::Vtable => {},
+    }
+    // Set allocation mutability as appropriate. This is used by LLVM to put things into
+    // read-only memory, and also by Miri when evluating other constants/statics that
+    // access this one.
+    if mode == InternMode::Static {
+        // When `ty` is `None`, we assume no interior mutability.
+        let frozen = ty.map_or(true, |ty| ty.is_freeze(
+            ecx.tcx.tcx,
+            ecx.param_env,
+            ecx.tcx.span,
+        ));
+        // For statics, allocation mutability is the combination of the place mutability and
+        // the type mutability.
+        // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
+        if mutability == Mutability::Immutable && frozen {
+            alloc.mutability = Mutability::Immutable;
+        } else {
+            // Just making sure we are not "upgrading" an immutable allocation to mutable.
+            assert_eq!(alloc.mutability, Mutability::Mutable);
+        }
+    } else {
+        // We *could* be non-frozen at `ConstBase`, for constants like `Cell::new(0)`.
+        // But we still intern that as immutable as the memory cannot be changed once the
+        // initial value was computed.
+        // Constants are never mutable.
+        assert_eq!(
+            mutability, Mutability::Immutable,
+            "Something went very wrong: mutability requested for a constant"
+        );
+        alloc.mutability = Mutability::Immutable;
+    };
+    // link the alloc id to the actual allocation
+    let alloc = tcx.intern_const_alloc(alloc);
+    leftover_allocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc));
+    tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
+    Ok(None)
+}
+
 impl<'rt, 'mir, 'tcx> InternVisitor<'rt, 'mir, 'tcx> {
-    /// Intern an allocation without looking at its children
     fn intern_shallow(
         &mut self,
-        ptr: Pointer,
+        alloc_id: AllocId,
         mutability: Mutability,
+        ty: Option<Ty<'tcx>>,
     ) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
-        trace!(
-            "InternVisitor::intern {:?} with {:?}",
-            ptr, mutability,
-        );
-        // remove allocation
-        let tcx = self.ecx.tcx;
-        let memory = self.ecx.memory_mut();
-        let (kind, mut alloc) = match memory.alloc_map.remove(&ptr.alloc_id) {
-            Some(entry) => entry,
-            None => {
-                // if the pointer is dangling (neither in local nor global memory), we leave it
-                // to validation to error. The `delay_span_bug` ensures that we don't forget such
-                // a check in validation.
-                if tcx.alloc_map.lock().get(ptr.alloc_id).is_none() {
-                    tcx.sess.delay_span_bug(self.ecx.tcx.span, "tried to intern dangling pointer");
-                }
-                // treat dangling pointers like other statics
-                // just to stop trying to recurse into them
-                return Ok(Some(IsStaticOrFn));
-            },
-        };
-        // This match is just a canary for future changes to `MemoryKind`, which most likely need
-        // changes in this function.
-        match kind {
-            MemoryKind::Stack | MemoryKind::Vtable => {},
-        }
-        // Ensure llvm knows to only put this into immutable memory if the value is immutable either
-        // by being behind a reference or by being part of a static or const without interior
-        // mutability
-        alloc.mutability = mutability;
-        // link the alloc id to the actual allocation
-        let alloc = tcx.intern_const_alloc(alloc);
-        self.leftover_relocations.extend(alloc.relocations.iter().map(|&(_, ((), reloc))| reloc));
-        tcx.alloc_map.lock().set_alloc_id_memory(ptr.alloc_id, alloc);
-        Ok(None)
+        intern_shallow(
+            self.ecx,
+            self.leftover_allocations,
+            self.mode,
+            alloc_id,
+            mutability,
+            ty,
+        )
     }
 }
 
@@ -119,14 +169,16 @@
     ) -> InterpResult<'tcx> {
         if let Some(def) = mplace.layout.ty.ty_adt_def() {
             if Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type() {
-                // We are crossing over an `UnsafeCell`, we can mutate again
+                // We are crossing over an `UnsafeCell`, we can mutate again. This means that
+                // References we encounter inside here are interned as pointing to mutable
+                // allocations.
                 let old = std::mem::replace(&mut self.mutability, Mutability::Mutable);
                 assert_ne!(
                     self.mode, InternMode::Const,
                     "UnsafeCells are not allowed behind references in constants. This should have \
                     been prevented statically by const qualification. If this were allowed one \
-                    would be able to change a constant at one use site and other use sites may \
-                    arbitrarily decide to change, too.",
+                    would be able to change a constant at one use site and other use sites could \
+                    observe that mutation.",
                 );
                 let walked = self.walk_aggregate(mplace, fields);
                 self.mutability = old;
@@ -145,12 +197,13 @@
             // Handle trait object vtables
             if let Ok(meta) = value.to_meta() {
                 if let ty::Dynamic(..) =
-                    self.ecx.tcx.struct_tail_erasing_lifetimes(referenced_ty, self.param_env).sty
+                    self.ecx.tcx.struct_tail_erasing_lifetimes(
+                        referenced_ty, self.ecx.param_env).sty
                 {
                     if let Ok(vtable) = meta.unwrap().to_ptr() {
                         // explitly choose `Immutable` here, since vtables are immutable, even
                         // if the reference of the fat pointer is mutable
-                        self.intern_shallow(vtable, Mutability::Immutable)?;
+                        self.intern_shallow(vtable.alloc_id, Mutability::Immutable, None)?;
                     }
                 }
             }
@@ -177,7 +230,7 @@
                     (InternMode::Const, hir::Mutability::MutMutable) => {
                         match referenced_ty.sty {
                             ty::Array(_, n)
-                                if n.eval_usize(self.ecx.tcx.tcx, self.param_env) == 0 => {}
+                                if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {}
                             ty::Slice(_)
                                 if value.to_meta().unwrap().unwrap().to_usize(self.ecx)? == 0 => {}
                             _ => bug!("const qualif failed to prevent mutable references"),
@@ -195,21 +248,13 @@
                     (Mutability::Mutable, hir::Mutability::MutMutable) => Mutability::Mutable,
                     _ => Mutability::Immutable,
                 };
-                // Compute the mutability of the allocation
-                let intern_mutability = intern_mutability(
-                    self.ecx.tcx.tcx,
-                    self.param_env,
-                    mplace.layout.ty,
-                    self.ecx.tcx.span,
-                    mutability,
-                );
                 // Recursing behind references changes the intern mode for constants in order to
                 // cause assertions to trigger if we encounter any `UnsafeCell`s.
                 let mode = match self.mode {
                     InternMode::ConstBase => InternMode::Const,
                     other => other,
                 };
-                match self.intern_shallow(ptr, intern_mutability)? {
+                match self.intern_shallow(ptr.alloc_id, mutability, Some(mplace.layout.ty))? {
                     // No need to recurse, these are interned already and statics may have
                     // cycles, so we don't want to recurse there
                     Some(IsStaticOrFn) => {},
@@ -224,69 +269,45 @@
     }
 }
 
-/// Figure out the mutability of the allocation.
-/// Mutable if it has interior mutability *anywhere* in the type.
-fn intern_mutability<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-    span: Span,
-    mutability: Mutability,
-) -> Mutability {
-    let has_interior_mutability = !ty.is_freeze(tcx, param_env, span);
-    if has_interior_mutability {
-        Mutability::Mutable
-    } else {
-        mutability
-    }
-}
-
 pub fn intern_const_alloc_recursive(
     ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
     def_id: DefId,
     ret: MPlaceTy<'tcx>,
-    // FIXME(oli-obk): can we scrap the param env? I think we can, the final value of a const eval
-    // must always be monomorphic, right?
-    param_env: ty::ParamEnv<'tcx>,
 ) -> InterpResult<'tcx> {
     let tcx = ecx.tcx;
     // this `mutability` is the mutability of the place, ignoring the type
-    let (mutability, base_intern_mode) = match tcx.static_mutability(def_id) {
+    let (base_mutability, base_intern_mode) = match tcx.static_mutability(def_id) {
         Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static),
-        None => (Mutability::Immutable, InternMode::ConstBase),
         // `static mut` doesn't care about interior mutability, it's mutable anyway
         Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static),
+        // consts, promoteds. FIXME: what about array lengths, array initializers?
+        None => (Mutability::Immutable, InternMode::ConstBase),
     };
 
-    // type based interning
-    let mut ref_tracking = RefTracking::new((ret, mutability, base_intern_mode));
-    let leftover_relocations = &mut FxHashSet::default();
-
-    // This mutability is the combination of the place mutability and the type mutability. If either
-    // is mutable, `alloc_mutability` is mutable. This exists because the entire allocation needs
-    // to be mutable if it contains an `UnsafeCell` anywhere. The other `mutability` exists so that
-    // the visitor does not treat everything outside the `UnsafeCell` as mutable.
-    let alloc_mutability = intern_mutability(
-        tcx.tcx, param_env, ret.layout.ty, tcx.span, mutability,
-    );
+    // Type based interning.
+    // `ref_tracking` tracks typed references we have seen and still need to crawl for
+    // more typed information inside them.
+    // `leftover_allocations` collects *all* allocations we see, because some might not
+    // be available in a typed way. They get interned at the end.
+    let mut ref_tracking = RefTracking::new((ret, base_mutability, base_intern_mode));
+    let leftover_allocations = &mut FxHashSet::default();
 
     // start with the outermost allocation
-    InternVisitor {
-        ref_tracking: &mut ref_tracking,
+    intern_shallow(
         ecx,
-        mode: base_intern_mode,
-        leftover_relocations,
-        param_env,
-        mutability,
-    }.intern_shallow(ret.ptr.to_ptr()?, alloc_mutability)?;
+        leftover_allocations,
+        base_intern_mode,
+        ret.ptr.to_ptr()?.alloc_id,
+        base_mutability,
+        Some(ret.layout.ty)
+    )?;
 
     while let Some(((mplace, mutability, mode), _)) = ref_tracking.todo.pop() {
         let interned = InternVisitor {
             ref_tracking: &mut ref_tracking,
             ecx,
             mode,
-            leftover_relocations,
-            param_env,
+            leftover_allocations,
             mutability,
         }.visit_value(mplace);
         if let Err(error) = interned {
@@ -309,15 +330,23 @@
     // Intern the rest of the allocations as mutable. These might be inside unions, padding, raw
     // pointers, ... So we can't intern them according to their type rules
 
-    let mut todo: Vec<_> = leftover_relocations.iter().cloned().collect();
+    let mut todo: Vec<_> = leftover_allocations.iter().cloned().collect();
     while let Some(alloc_id) = todo.pop() {
-        if let Some((_, alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) {
-            // We can't call the `intern` method here, as its logic is tailored to safe references.
-            // So we hand-roll the interning logic here again
+        if let Some((_, mut alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) {
+            // We can't call the `intern_shallow` method here, as its logic is tailored to safe
+            // references and a `leftover_allocations` set (where we only have a todo-list here).
+            // So we hand-roll the interning logic here again.
+            if base_intern_mode != InternMode::Static {
+                // If it's not a static, it *must* be immutable.
+                // We cannot have mutable memory inside a constant.
+                // FIXME: ideally we would assert that they already are immutable, to double-
+                // check our static checks.
+                alloc.mutability = Mutability::Immutable;
+            }
             let alloc = tcx.intern_const_alloc(alloc);
             tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
-            for &(_, ((), reloc)) in alloc.relocations.iter() {
-                if leftover_relocations.insert(reloc) {
+            for &(_, ((), reloc)) in alloc.relocations().iter() {
+                if leftover_allocations.insert(reloc) {
                     todo.push(reloc);
                 }
             }
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 334f1ea..ec09e69 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -5,17 +5,18 @@
 use syntax::symbol::Symbol;
 use rustc::ty;
 use rustc::ty::layout::{LayoutOf, Primitive, Size};
+use rustc::ty::subst::SubstsRef;
+use rustc::hir::def_id::DefId;
+use rustc::ty::TyCtxt;
 use rustc::mir::BinOp;
-use rustc::mir::interpret::{InterpResult, Scalar};
+use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue};
 
 use super::{
-    Machine, PlaceTy, OpTy, InterpCx, Immediate,
+    Machine, PlaceTy, OpTy, InterpCx,
 };
 
 mod type_name;
 
-pub use type_name::*;
-
 fn numeric_intrinsic<'tcx, Tag>(
     name: &str,
     bits: u128,
@@ -37,6 +38,50 @@
     Ok(Scalar::from_uint(bits_out, size))
 }
 
+/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
+/// inside an `InterpCx` and instead have their value computed directly from rustc internal info.
+crate fn eval_nullary_intrinsic<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    def_id: DefId,
+    substs: SubstsRef<'tcx>,
+) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
+    let tp_ty = substs.type_at(0);
+    let name = &*tcx.item_name(def_id).as_str();
+    Ok(match name {
+        "type_name" => {
+            let alloc = type_name::alloc_type_name(tcx, tp_ty);
+            tcx.mk_const(ty::Const {
+                val: ConstValue::Slice {
+                    data: alloc,
+                    start: 0,
+                    end: alloc.len(),
+                },
+                ty: tcx.mk_static_str(),
+            })
+        },
+        "needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
+        "size_of" |
+        "min_align_of" |
+        "pref_align_of" => {
+            let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
+            let n = match name {
+                "pref_align_of" => layout.align.pref.bytes(),
+                "min_align_of" => layout.align.abi.bytes(),
+                "size_of" => layout.size.bytes(),
+                _ => bug!(),
+            };
+            ty::Const::from_usize(tcx, n)
+        },
+        "type_id" => ty::Const::from_bits(
+            tcx,
+            tcx.type_id_hash(tp_ty).into(),
+            param_env.and(tcx.types.u64),
+        ),
+        other => bug!("`{}` is not a zero arg intrinsic", other),
+    })
+}
+
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Returns `true` if emulation happened.
     pub fn emulate_intrinsic(
@@ -49,41 +94,19 @@
 
         let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
         match intrinsic_name {
-            "min_align_of" => {
-                let elem_ty = substs.type_at(0);
-                let elem_align = self.layout_of(elem_ty)?.align.abi.bytes();
-                let align_val = Scalar::from_uint(elem_align, dest.layout.size);
-                self.write_scalar(align_val, dest)?;
-            }
-
-            "needs_drop" => {
-                let ty = substs.type_at(0);
-                let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env);
-                let val = Scalar::from_bool(ty_needs_drop);
-                self.write_scalar(val, dest)?;
-            }
-
-            "size_of" => {
-                let ty = substs.type_at(0);
-                let size = self.layout_of(ty)?.size.bytes() as u128;
-                let size_val = Scalar::from_uint(size, dest.layout.size);
-                self.write_scalar(size_val, dest)?;
-            }
-
-            "type_id" => {
-                let ty = substs.type_at(0);
-                let type_id = self.tcx.type_id_hash(ty) as u128;
-                let id_val = Scalar::from_uint(type_id, dest.layout.size);
-                self.write_scalar(id_val, dest)?;
-            }
-
+            "min_align_of" |
+            "pref_align_of" |
+            "needs_drop" |
+            "size_of" |
+            "type_id" |
             "type_name" => {
-                let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0));
-                let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
-                let id_ptr = self.memory.tag_static_base_pointer(name_id.into());
-                let alloc_len = alloc.bytes.len() as u64;
-                let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self);
-                self.write_immediate(name_val, dest)?;
+                let gid = GlobalId {
+                    instance,
+                    promoted: None,
+                };
+                let val = self.tcx.const_eval(self.param_env.and(gid))?;
+                let val = self.eval_const_to_op(val, None)?;
+                self.copy_op(val, dest)?;
             }
 
             | "ctpop"
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index f207cfc..1e765a4 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -7,7 +7,7 @@
 use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
 use rustc::hir::def_id::CrateNum;
 use std::fmt::Write;
-use rustc::mir::interpret::{Allocation, ConstValue};
+use rustc::mir::interpret::Allocation;
 
 struct AbsolutePathPrinter<'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -213,22 +213,11 @@
     }
 }
 
-/// Produces an absolute path representation of the given type. See also the documentation on
-/// `std::any::type_name`
-pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
-    let alloc = alloc_type_name(tcx, ty);
-    tcx.mk_const(ty::Const {
-        val: ConstValue::Slice {
-            data: alloc,
-            start: 0,
-            end: alloc.bytes.len(),
-        },
-        ty: tcx.mk_static_str(),
-    })
-}
-
 /// Directly returns an `Allocation` containing an absolute path representation of the given type.
-pub(super) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
+crate fn alloc_type_name<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>
+) -> &'tcx Allocation {
     let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
     let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
     tcx.intern_const_alloc(alloc)
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 87d36da..62b1760 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -210,7 +210,7 @@
         let new_ptr = self.allocate(new_size, new_align, kind);
         let old_size = match old_size_and_align {
             Some((size, _align)) => size,
-            None => Size::from_bytes(self.get(ptr.alloc_id)?.bytes.len() as u64),
+            None => self.get(ptr.alloc_id)?.size,
         };
         self.copy(
             ptr,
@@ -271,20 +271,20 @@
             ))
         }
         if let Some((size, align)) = old_size_and_align {
-            if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align {
-                let bytes = Size::from_bytes(alloc.bytes.len() as u64);
+            if size != alloc.size || align != alloc.align {
+                let bytes = alloc.size;
                 throw_unsup!(IncorrectAllocationInformation(size, bytes, align, alloc.align))
             }
         }
 
         // Let the machine take some extra action
-        let size = Size::from_bytes(alloc.bytes.len() as u64);
+        let size = alloc.size;
         AllocationExtra::memory_deallocated(&mut alloc, ptr, size)?;
 
         // Don't forget to remember size and align of this now-dead allocation
         let old = self.dead_alloc_map.insert(
             ptr.alloc_id,
-            (Size::from_bytes(alloc.bytes.len() as u64), alloc.align)
+            (alloc.size, alloc.align)
         );
         if old.is_some() {
             bug!("Nothing can be deallocated twice");
@@ -555,7 +555,7 @@
         // a) cause cycles in case `id` refers to a static
         // b) duplicate a static's allocation in miri
         if let Some((_, alloc)) = self.alloc_map.get(id) {
-            return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
+            return Ok((alloc.size, alloc.align));
         }
 
         // # Function pointers
@@ -583,7 +583,7 @@
             Some(GlobalAlloc::Memory(alloc)) =>
                 // Need to duplicate the logic here, because the global allocations have
                 // different associated types than the interpreter-local ones.
-                Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
+                Ok((alloc.size, alloc.align)),
             Some(GlobalAlloc::Function(_)) =>
                 bug!("We already checked function pointers above"),
             // The rest must be dead.
@@ -645,17 +645,22 @@
         let prefix_len = msg.len();
         let mut relocations = vec![];
 
-        for i in 0..(alloc.bytes.len() as u64) {
+        for i in 0..alloc.size.bytes() {
             let i = Size::from_bytes(i);
-            if let Some(&(_, target_id)) = alloc.relocations.get(&i) {
+            if let Some(&(_, target_id)) = alloc.relocations().get(&i) {
                 if allocs_seen.insert(target_id) {
                     allocs_to_print.push_back(target_id);
                 }
                 relocations.push((i, target_id));
             }
-            if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() {
+            if alloc.undef_mask().is_range_defined(i, i + Size::from_bytes(1)).is_ok() {
                 // this `as usize` is fine, since `i` came from a `usize`
-                write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap();
+                let i = i.bytes() as usize;
+
+                // Checked definedness (and thus range) and relocations. This access also doesn't
+                // influence interpreter execution but is only for debugging.
+                let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(i..i+1);
+                write!(msg, "{:02x} ", bytes[0]).unwrap();
             } else {
                 msg.push_str("__ ");
             }
@@ -664,7 +669,7 @@
         trace!(
             "{}({} bytes, alignment {}){}",
             msg,
-            alloc.bytes.len(),
+            alloc.size.bytes(),
             alloc.align.bytes(),
             extra
         );
@@ -803,32 +808,8 @@
         // since we don't want to keep any relocations at the target.
         // (`get_bytes_with_undef_and_ptr` below checks that there are no
         // relocations overlapping the edges; those would not be handled correctly).
-        let relocations = {
-            let relocations = self.get(src.alloc_id)?.relocations(self, src, size);
-            if relocations.is_empty() {
-                // nothing to copy, ignore even the `length` loop
-                Vec::new()
-            } else {
-                let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize));
-                for i in 0..length {
-                    new_relocations.extend(
-                        relocations
-                        .iter()
-                        .map(|&(offset, reloc)| {
-                            // compute offset for current repetition
-                            let dest_offset = dest.offset + (i * size);
-                            (
-                                // shift offsets from source allocation to destination allocation
-                                offset + dest_offset - src.offset,
-                                reloc,
-                            )
-                        })
-                    );
-                }
-
-                new_relocations
-            }
-        };
+        let relocations = self.get(src.alloc_id)?
+            .prepare_relocation_copy(self, src, size, dest, length);
 
         let tcx = self.tcx.tcx;
 
@@ -875,7 +856,7 @@
         // copy definedness to the destination
         self.copy_undef_mask(src, dest, size, length)?;
         // copy the relocations to the destination
-        self.get_mut(dest.alloc_id)?.relocations.insert_presorted(relocations);
+        self.get_mut(dest.alloc_id)?.mark_relocation_range(relocations);
 
         Ok(())
     }
@@ -894,65 +875,13 @@
         // The bits have to be saved locally before writing to dest in case src and dest overlap.
         assert_eq!(size.bytes() as usize as u64, size.bytes());
 
-        let undef_mask = &self.get(src.alloc_id)?.undef_mask;
-
-        // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`),
-        // a naive undef mask copying algorithm would repeatedly have to read the undef mask from
-        // the source and write it to the destination. Even if we optimized the memory accesses,
-        // we'd be doing all of this `repeat` times.
-        // Therefor we precompute a compressed version of the undef mask of the source value and
-        // then write it back `repeat` times without computing any more information from the source.
-
-        // a precomputed cache for ranges of defined/undefined bits
-        // 0000010010001110 will become
-        // [5, 1, 2, 1, 3, 3, 1]
-        // where each element toggles the state
-        let mut ranges = smallvec::SmallVec::<[u64; 1]>::new();
-        let first = undef_mask.get(src.offset);
-        let mut cur_len = 1;
-        let mut cur = first;
-        for i in 1..size.bytes() {
-            // FIXME: optimize to bitshift the current undef block's bits and read the top bit
-            if undef_mask.get(src.offset + Size::from_bytes(i)) == cur {
-                cur_len += 1;
-            } else {
-                ranges.push(cur_len);
-                cur_len = 1;
-                cur = !cur;
-            }
-        }
+        let src_alloc = self.get(src.alloc_id)?;
+        let compressed = src_alloc.compress_undef_range(src, size);
 
         // now fill in all the data
         let dest_allocation = self.get_mut(dest.alloc_id)?;
-        // an optimization where we can just overwrite an entire range of definedness bits if
-        // they are going to be uniformly `1` or `0`.
-        if ranges.is_empty() {
-            dest_allocation.undef_mask.set_range_inbounds(
-                dest.offset,
-                dest.offset + size * repeat,
-                first,
-            );
-            return Ok(())
-        }
+        dest_allocation.mark_compressed_undef_range(&compressed, dest, size, repeat);
 
-        // remember to fill in the trailing bits
-        ranges.push(cur_len);
-
-        for mut j in 0..repeat {
-            j *= size.bytes();
-            j += dest.offset.bytes();
-            let mut cur = first;
-            for range in &ranges {
-                let old_j = j;
-                j += range;
-                dest_allocation.undef_mask.set_range_inbounds(
-                    Size::from_bytes(old_j),
-                    Size::from_bytes(j),
-                    cur,
-                );
-                cur = !cur;
-            }
-        }
         Ok(())
     }
 
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 45d2434..0c61be2 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -34,6 +34,6 @@
 
 pub use self::validity::RefTracking;
 
-pub(super) use self::intrinsics::type_name;
-
 pub use self::intern::intern_const_alloc_recursive;
+
+crate use self::intrinsics::eval_nullary_intrinsic;
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index b5aab99..9ad1542 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -472,39 +472,38 @@
     // avoid allocations.
     pub(super) fn eval_place_to_op(
         &self,
-        mir_place: &mir::Place<'tcx>,
+        place: &mir::Place<'tcx>,
         layout: Option<TyLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::PlaceBase;
 
-        mir_place.iterate(|place_base, place_projection| {
-            let mut op = match place_base {
-                PlaceBase::Local(mir::RETURN_PLACE) =>
-                    throw_unsup!(ReadFromReturnPointer),
-                PlaceBase::Local(local) => {
-                    // Do not use the layout passed in as argument if the base we are looking at
-                    // here is not the entire place.
-                    // FIXME use place_projection.is_empty() when is available
-                    let layout = if mir_place.projection.is_none() {
-                        layout
-                    } else {
-                        None
-                    };
+        let base_op = match &place.base {
+            PlaceBase::Local(mir::RETURN_PLACE) =>
+                throw_unsup!(ReadFromReturnPointer),
+            PlaceBase::Local(local) => {
+                // Do not use the layout passed in as argument if the base we are looking at
+                // here is not the entire place.
+                // FIXME use place_projection.is_empty() when is available
+                let layout = if place.projection.is_empty() {
+                    layout
+                } else {
+                    None
+                };
 
-                    self.access_local(self.frame(), *local, layout)?
-                }
-                PlaceBase::Static(place_static) => {
-                    self.eval_static_to_mplace(place_static)?.into()
-                }
-            };
-
-            for proj in place_projection {
-                op = self.operand_projection(op, &proj.elem)?
+                self.access_local(self.frame(), *local, layout)?
             }
+            PlaceBase::Static(place_static) => {
+                self.eval_static_to_mplace(&place_static)?.into()
+            }
+        };
 
-            trace!("eval_place_to_op: got {:?}", *op);
-            Ok(op)
-        })
+        let op = place.projection.iter().try_fold(
+            base_op,
+            |op, elem| self.operand_projection(op, elem)
+        )?;
+
+        trace!("eval_place_to_op: got {:?}", *op);
+        Ok(op)
     }
 
     /// Evaluate the operand, returning a place where you can then find the data.
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 23c9e7f..1a28548 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -585,8 +585,9 @@
         use rustc::mir::StaticKind;
 
         Ok(match place_static.kind {
-            StaticKind::Promoted(promoted, _) => {
-                let instance = self.frame().instance;
+            StaticKind::Promoted(promoted, promoted_substs) => {
+                let substs = self.subst_from_frame_and_normalize_erasing_regions(promoted_substs);
+                let instance = ty::Instance::new(place_static.def_id, substs);
                 self.const_eval_raw(GlobalId {
                     instance,
                     promoted: Some(promoted),
@@ -628,45 +629,43 @@
     /// place; for reading, a more efficient alternative is `eval_place_for_read`.
     pub fn eval_place(
         &mut self,
-        mir_place: &mir::Place<'tcx>,
+        place: &mir::Place<'tcx>,
     ) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::PlaceBase;
 
-        mir_place.iterate(|place_base, place_projection| {
-            let mut place = match place_base {
-                PlaceBase::Local(mir::RETURN_PLACE) => match self.frame().return_place {
-                    Some(return_place) => {
-                        // We use our layout to verify our assumption; caller will validate
-                        // their layout on return.
-                        PlaceTy {
-                            place: *return_place,
-                            layout: self.layout_of(
-                                self.subst_from_frame_and_normalize_erasing_regions(
-                                    self.frame().body.return_ty()
-                                )
-                            )?,
-                        }
+        let mut place_ty = match &place.base {
+            PlaceBase::Local(mir::RETURN_PLACE) => match self.frame().return_place {
+                Some(return_place) => {
+                    // We use our layout to verify our assumption; caller will validate
+                    // their layout on return.
+                    PlaceTy {
+                        place: *return_place,
+                        layout: self.layout_of(
+                            self.subst_from_frame_and_normalize_erasing_regions(
+                                self.frame().body.return_ty()
+                            )
+                        )?,
                     }
-                    None => throw_unsup!(InvalidNullPointerUsage),
+                }
+                None => throw_unsup!(InvalidNullPointerUsage),
+            },
+            PlaceBase::Local(local) => PlaceTy {
+                // This works even for dead/uninitialized locals; we check further when writing
+                place: Place::Local {
+                    frame: self.cur_frame(),
+                    local: *local,
                 },
-                PlaceBase::Local(local) => PlaceTy {
-                    // This works even for dead/uninitialized locals; we check further when writing
-                    place: Place::Local {
-                        frame: self.cur_frame(),
-                        local: *local,
-                    },
-                    layout: self.layout_of_local(self.frame(), *local, None)?,
-                },
-                PlaceBase::Static(place_static) => self.eval_static_to_mplace(place_static)?.into(),
-            };
+                layout: self.layout_of_local(self.frame(), *local, None)?,
+            },
+            PlaceBase::Static(place_static) => self.eval_static_to_mplace(&place_static)?.into(),
+        };
 
-            for proj in place_projection {
-                place = self.place_projection(place, &proj.elem)?
-            }
+        for elem in place.projection.iter() {
+            place_ty = self.place_projection(place_ty, elem)?
+        }
 
-            self.dump_place(place.place);
-            Ok(place)
-        })
+        self.dump_place(place_ty.place);
+        Ok(place_ty)
     }
 
     /// Write a scalar to a place
diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index 4728906..2cac8bb 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -15,7 +15,7 @@
 };
 
 use rustc::ty::{self, TyCtxt};
-use rustc::ty::layout::Align;
+use rustc::ty::layout::{Align, Size};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -276,6 +276,7 @@
     relocations: Relocations<(), AllocIdSnapshot<'a>>,
     undef_mask: &'a UndefMask,
     align: &'a Align,
+    size: &'a Size,
     mutability: &'a Mutability,
 }
 
@@ -285,12 +286,28 @@
     type Item = AllocationSnapshot<'a>;
 
     fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
-        let Allocation { bytes, relocations, undef_mask, align, mutability, extra: () } = self;
+        let Allocation {
+            size,
+            align,
+            mutability,
+            extra: (),
+            ..
+        } = self;
+
+        let all_bytes = 0..self.len();
+        // This 'inspect' is okay since following access respects undef and relocations. This does
+        // influence interpreter exeuction, but only to detect the error of cycles in evalution
+        // dependencies.
+        let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(all_bytes);
+
+        let undef_mask = self.undef_mask();
+        let relocations = self.relocations();
 
         AllocationSnapshot {
             bytes,
             undef_mask,
             align,
+            size,
             mutability,
             relocations: relocations.snapshot(ctx),
         }
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index ca4da45..affca10 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -82,7 +82,7 @@
         self.memory.tcx.span = stmt.source_info.span;
 
         match stmt.kind {
-            Assign(ref place, ref rvalue) => self.eval_rvalue_into_place(rvalue, place)?,
+            Assign(box(ref place, ref rvalue)) => self.eval_rvalue_into_place(rvalue, place)?,
 
             SetDiscriminant {
                 ref place,
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 5de2979..8310ef0 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -391,7 +391,7 @@
                     // Don't forget to check the return type!
                     if let Some(caller_ret) = dest {
                         let callee_ret = self.eval_place(
-                            &mir::Place::RETURN_PLACE
+                            &mir::Place::return_place()
                         )?;
                         if !Self::check_argument_compat(
                             rust_abi,
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index 34a10de..10b767e 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -1,5 +1,5 @@
 use rustc::ty::{self, Ty, Instance, TypeFoldable};
-use rustc::ty::layout::{Size, Align, LayoutOf};
+use rustc::ty::layout::{Size, Align, LayoutOf, HasDataLayout};
 use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic,};
 
 use super::{InterpCx, Machine, MemoryKind, FnVal};
@@ -151,6 +151,11 @@
             vtable.offset(pointer_size * 2, self)?,
         )?.not_undef()?;
         let align = self.force_bits(align, pointer_size)? as u64;
+
+        if size >= self.tcx.data_layout().obj_size_bound() {
+            throw_ub_format!("invalid vtable: \
+                size is bigger than largest supported object");
+        }
         Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap()))
     }
 }
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index c250554..3e14ba3 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -1,3 +1,9 @@
+//! Check the validity invariant of a given value, and tell the user
+//! where in the value it got violated.
+//! In const context, this goes even further and tries to approximate const safety.
+//! That's useful because it means other passes (e.g. promotion) can rely on `const`s
+//! to be const-safe.
+
 use std::fmt::Write;
 use std::ops::RangeInclusive;
 
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index cccf7b9..6a49ed6 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -14,7 +14,6 @@
 #![feature(const_fn)]
 #![feature(decl_macro)]
 #![feature(exhaustive_patterns)]
-#![feature(rustc_diagnostic_macros)]
 #![feature(never_type)]
 #![feature(specialization)]
 #![feature(try_trait)]
@@ -32,11 +31,11 @@
 #[macro_use] extern crate rustc_data_structures;
 #[macro_use] extern crate syntax;
 
-mod error_codes;
+pub mod error_codes;
 
 mod borrow_check;
 mod build;
-mod dataflow;
+pub mod dataflow;
 mod hair;
 mod lints;
 mod shim;
@@ -60,7 +59,4 @@
         let (param_env, (value, field)) = param_env_and_value.into_parts();
         const_eval::const_field(tcx, param_env, None, field, value)
     };
-    providers.type_name = interpret::type_name;
 }
-
-__build_diagnostic_array! { librustc_mir, DIAGNOSTICS }
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 11f9df6..1f7efeb 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -1218,7 +1218,7 @@
         }
         Some(GlobalAlloc::Memory(alloc)) => {
             trace!("collecting {:?} with {:#?}", alloc_id, alloc);
-            for &((), inner) in alloc.relocations.values() {
+            for &((), inner) in alloc.relocations().values() {
                 collect_miri(tcx, inner, output);
             }
         },
@@ -1269,7 +1269,7 @@
             collect_miri(tcx, ptr.alloc_id, output),
         ConstValue::Slice { data: alloc, start: _, end: _ } |
         ConstValue::ByRef { alloc, .. } => {
-            for &((), id) in alloc.relocations.values() {
+            for &((), id) in alloc.relocations().values() {
                 collect_miri(tcx, id, output);
             }
         }
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index ad9db4e..c193911 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -777,7 +777,7 @@
             debug!("CodegenUnit {}:", cgu.name());
 
             for (mono_item, linkage) in cgu.items() {
-                let symbol_name = mono_item.symbol_name(tcx).as_str();
+                let symbol_name = mono_item.symbol_name(tcx).name.as_str();
                 let symbol_hash_start = symbol_name.rfind('h');
                 let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
                                                    .unwrap_or("<no hash>");
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index aa83255..6daca5e 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -217,7 +217,7 @@
             // Function arguments should be retagged, and we make this one raw.
             body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
                 source_info,
-                kind: StatementKind::Retag(RetagKind::Raw, dropee_ptr.clone()),
+                kind: StatementKind::Retag(RetagKind::Raw, box(dropee_ptr.clone())),
             });
         }
         let patch = {
@@ -308,7 +308,7 @@
     let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
     let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env, builder.span);
 
-    let dest = Place::RETURN_PLACE;
+    let dest = Place::return_place();
     let src = Place::from(Local::new(1+0)).deref();
 
     match self_ty.sty {
@@ -415,8 +415,10 @@
         let rcvr = Place::from(Local::new(1+0)).deref();
         let ret_statement = self.make_statement(
             StatementKind::Assign(
-                Place::RETURN_PLACE,
-                box Rvalue::Use(Operand::Copy(rcvr))
+                box(
+                    Place::return_place(),
+                    Rvalue::Use(Operand::Copy(rcvr))
+                )
             )
         );
         self.block(vec![ret_statement], TerminatorKind::Return, false);
@@ -458,8 +460,10 @@
         // `let ref_loc: &ty = &src;`
         let statement = self.make_statement(
             StatementKind::Assign(
-                ref_loc.clone(),
-                box Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, src)
+                box(
+                    ref_loc.clone(),
+                    Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, src)
+                )
             )
         );
 
@@ -486,8 +490,10 @@
         let cond = self.make_place(Mutability::Mut, tcx.types.bool);
         let compute_cond = self.make_statement(
             StatementKind::Assign(
-                cond.clone(),
-                box Rvalue::BinaryOp(BinOp::Ne, Operand::Copy(end), Operand::Copy(beg))
+                box(
+                    cond.clone(),
+                    Rvalue::BinaryOp(BinOp::Ne, Operand::Copy(end), Operand::Copy(beg))
+                )
             )
         );
 
@@ -521,14 +527,18 @@
         let inits = vec![
             self.make_statement(
                 StatementKind::Assign(
-                    Place::from(beg),
-                    box Rvalue::Use(Operand::Constant(self.make_usize(0)))
+                    box(
+                        Place::from(beg),
+                        Rvalue::Use(Operand::Constant(self.make_usize(0)))
+                    )
                 )
             ),
             self.make_statement(
                 StatementKind::Assign(
-                    end.clone(),
-                    box Rvalue::Use(Operand::Constant(self.make_usize(len)))
+                    box(
+                        end.clone(),
+                        Rvalue::Use(Operand::Constant(self.make_usize(len)))
+                    )
                 )
             )
         ];
@@ -559,11 +569,13 @@
         let statements = vec![
             self.make_statement(
                 StatementKind::Assign(
-                    Place::from(beg),
-                    box Rvalue::BinaryOp(
-                        BinOp::Add,
-                        Operand::Copy(Place::from(beg)),
-                        Operand::Constant(self.make_usize(1))
+                    box(
+                        Place::from(beg),
+                        Rvalue::BinaryOp(
+                            BinOp::Add,
+                            Operand::Copy(Place::from(beg)),
+                            Operand::Constant(self.make_usize(1))
+                        )
                     )
                 )
             )
@@ -582,8 +594,10 @@
         let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
         let init = self.make_statement(
             StatementKind::Assign(
-                Place::from(beg),
-                box Rvalue::Use(Operand::Constant(self.make_usize(0)))
+                box(
+                    Place::from(beg),
+                    Rvalue::Use(Operand::Constant(self.make_usize(0)))
+                )
             )
         );
         self.block(vec![init], TerminatorKind::Goto { target: BasicBlock::new(6) }, true);
@@ -609,11 +623,13 @@
         // `goto #6;`
         let statement = self.make_statement(
             StatementKind::Assign(
-                Place::from(beg),
-                box Rvalue::BinaryOp(
-                    BinOp::Add,
-                    Operand::Copy(Place::from(beg)),
-                    Operand::Constant(self.make_usize(1))
+                box(
+                    Place::from(beg),
+                    Rvalue::BinaryOp(
+                        BinOp::Add,
+                        Operand::Copy(Place::from(beg)),
+                        Operand::Constant(self.make_usize(1))
+                    )
                 )
             )
         );
@@ -727,8 +743,10 @@
             statements.push(Statement {
                 source_info,
                 kind: StatementKind::Assign(
-                    Place::from(ref_rcvr),
-                    box Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_l)
+                    box(
+                        Place::from(ref_rcvr),
+                        Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_l)
+                    )
                 )
             });
             Operand::Move(Place::from(ref_rcvr))
@@ -773,7 +791,7 @@
     block(&mut blocks, statements, TerminatorKind::Call {
         func: callee,
         args,
-        destination: Some((Place::RETURN_PLACE,
+        destination: Some((Place::return_place(),
                            BasicBlock::new(1))),
         cleanup: if let Adjustment::RefMut = rcvr_adjustment {
             Some(BasicBlock::new(3))
@@ -868,7 +886,7 @@
     debug!("build_ctor: variant_index={:?}", variant_index);
 
     let statements = expand_aggregate(
-        Place::RETURN_PLACE,
+        Place::return_place(),
         adt_def
             .variants[variant_index]
             .fields
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index 0fd75cd..833c8b1 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -17,12 +17,11 @@
 fn is_stable(
     place: PlaceRef<'_, '_>,
 ) -> bool {
-    if let Some(proj) = &place.projection {
-        match proj.elem {
+    place.projection.iter().all(|elem| {
+        match elem {
             // Which place this evaluates to can change with any memory write,
             // so cannot assume this to be stable.
-            ProjectionElem::Deref =>
-                false,
+            ProjectionElem::Deref => false,
             // Array indices are intersting, but MIR building generates a *fresh*
             // temporary for every array access, so the index cannot be changed as
             // a side-effect.
@@ -31,15 +30,9 @@
             ProjectionElem::Field { .. } |
             ProjectionElem::ConstantIndex { .. } |
             ProjectionElem::Subslice { .. } |
-            ProjectionElem::Downcast { .. } =>
-                is_stable(PlaceRef {
-                    base: place.base,
-                    projection: &proj.base,
-                }),
+            ProjectionElem::Downcast { .. } => true,
         }
-    } else {
-        true
-    }
+    })
 }
 
 /// Determine whether this type may be a reference (or box), and thus needs retagging.
@@ -96,7 +89,7 @@
             basic_blocks[START_BLOCK].statements.splice(0..0,
                 places.into_iter().map(|place| Statement {
                     source_info,
-                    kind: StatementKind::Retag(RetagKind::FnEntry, place),
+                    kind: StatementKind::Retag(RetagKind::FnEntry, box(place)),
                 })
             );
         }
@@ -132,7 +125,7 @@
         for (source_info, dest_place, dest_block) in returns {
             basic_blocks[dest_block].statements.insert(0, Statement {
                 source_info,
-                kind: StatementKind::Retag(RetagKind::Default, dest_place),
+                kind: StatementKind::Retag(RetagKind::Default, box(dest_place)),
             });
         }
 
@@ -144,11 +137,11 @@
             for i in (0..block_data.statements.len()).rev() {
                 let (retag_kind, place) = match block_data.statements[i].kind {
                     // If we are casting *from* a reference, we may have to retag-as-raw.
-                    StatementKind::Assign(ref place, box Rvalue::Cast(
+                    StatementKind::Assign(box(ref place, Rvalue::Cast(
                         CastKind::Misc,
                         ref src,
                         dest_ty,
-                    )) => {
+                    ))) => {
                         let src_ty = src.ty(&*local_decls, tcx);
                         if src_ty.is_region_ptr() {
                             // The only `Misc` casts on references are those creating raw pointers.
@@ -162,7 +155,7 @@
                     // Assignments of reference or ptr type are the ones where we may have
                     // to update tags.  This includes `x = &[mut] ...` and hence
                     // we also retag after taking a reference!
-                    StatementKind::Assign(ref place, box ref rvalue) if needs_retag(place) => {
+                    StatementKind::Assign(box(ref place, ref rvalue)) if needs_retag(place) => {
                         let kind = match rvalue {
                             Rvalue::Ref(_, borrow_kind, _)
                                 if borrow_kind.allows_two_phase_borrow()
@@ -180,7 +173,7 @@
                 let source_info = block_data.statements[i].source_info;
                 block_data.statements.insert(i+1, Statement {
                     source_info,
-                    kind: StatementKind::Retag(retag_kind, place),
+                    kind: StatementKind::Retag(retag_kind, box(place)),
                 });
             }
         }
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 539922c..39aa5c7 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -200,127 +200,127 @@
                     place: &Place<'tcx>,
                     context: PlaceContext,
                     _location: Location) {
-        place.iterate(|place_base, place_projections| {
-            match place_base {
-                PlaceBase::Local(..) => {
-                    // Locals are safe.
-                }
-                PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => {
-                    bug!("unsafety checking should happen before promotion")
-                }
-                PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => {
-                    if self.tcx.is_mutable_static(*def_id) {
-                        self.require_unsafe("use of mutable static",
-                            "mutable statics can be mutated by multiple threads: aliasing \
-                             violations or data races will cause undefined behavior",
-                             UnsafetyViolationKind::General);
-                    } else if self.tcx.is_foreign_item(*def_id) {
-                        let source_info = self.source_info;
-                        let lint_root =
-                            self.source_scope_local_data[source_info.scope].lint_root;
-                        self.register_violations(&[UnsafetyViolation {
-                            source_info,
-                            description: InternedString::intern("use of extern static"),
-                            details: InternedString::intern(
-                                "extern statics are not controlled by the Rust type system: \
-                                invalid data, aliasing violations or data races will cause \
-                                undefined behavior"),
-                            kind: UnsafetyViolationKind::ExternStatic(lint_root)
-                        }], &[]);
-                    }
+        match place.base {
+            PlaceBase::Local(..) => {
+                // Locals are safe.
+            }
+            PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => {
+                bug!("unsafety checking should happen before promotion")
+            }
+            PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => {
+                if self.tcx.is_mutable_static(def_id) {
+                    self.require_unsafe("use of mutable static",
+                        "mutable statics can be mutated by multiple threads: aliasing \
+                         violations or data races will cause undefined behavior",
+                         UnsafetyViolationKind::General);
+                } else if self.tcx.is_foreign_item(def_id) {
+                    let source_info = self.source_info;
+                    let lint_root =
+                        self.source_scope_local_data[source_info.scope].lint_root;
+                    self.register_violations(&[UnsafetyViolation {
+                        source_info,
+                        description: InternedString::intern("use of extern static"),
+                        details: InternedString::intern(
+                            "extern statics are not controlled by the Rust type system: \
+                            invalid data, aliasing violations or data races will cause \
+                            undefined behavior"),
+                        kind: UnsafetyViolationKind::ExternStatic(lint_root)
+                    }], &[]);
                 }
             }
+        }
 
-            for proj in place_projections {
-                if context.is_borrow() {
-                    if util::is_disaligned(self.tcx, self.body, self.param_env, place) {
-                        let source_info = self.source_info;
-                        let lint_root =
-                            self.source_scope_local_data[source_info.scope].lint_root;
-                        self.register_violations(&[UnsafetyViolation {
-                            source_info,
-                            description: InternedString::intern("borrow of packed field"),
-                            details: InternedString::intern(
-                                "fields of packed structs might be misaligned: dereferencing a \
-                                misaligned pointer or even just creating a misaligned reference \
-                                is undefined behavior"),
-                            kind: UnsafetyViolationKind::BorrowPacked(lint_root)
-                        }], &[]);
-                    }
+        for (i, elem) in place.projection.iter().enumerate() {
+            let proj_base = &place.projection[..i];
+
+            if context.is_borrow() {
+                if util::is_disaligned(self.tcx, self.body, self.param_env, place) {
+                    let source_info = self.source_info;
+                    let lint_root =
+                        self.source_scope_local_data[source_info.scope].lint_root;
+                    self.register_violations(&[UnsafetyViolation {
+                        source_info,
+                        description: InternedString::intern("borrow of packed field"),
+                        details: InternedString::intern(
+                            "fields of packed structs might be misaligned: dereferencing a \
+                            misaligned pointer or even just creating a misaligned reference \
+                            is undefined behavior"),
+                        kind: UnsafetyViolationKind::BorrowPacked(lint_root)
+                    }], &[]);
                 }
-                let is_borrow_of_interior_mut = context.is_borrow() &&
-                    !Place::ty_from(&place.base, &proj.base, self.body, self.tcx)
-                    .ty
-                    .is_freeze(self.tcx, self.param_env, self.source_info.span);
-                // prevent
-                // * `&mut x.field`
-                // * `x.field = y;`
-                // * `&x.field` if `field`'s type has interior mutability
-                // because either of these would allow modifying the layout constrained field and
-                // insert values that violate the layout constraints.
-                if context.is_mutating_use() || is_borrow_of_interior_mut {
-                    self.check_mut_borrowing_layout_constrained_field(
-                        place, context.is_mutating_use(),
-                    );
+            }
+            let is_borrow_of_interior_mut = context.is_borrow() &&
+                !Place::ty_from(&place.base, proj_base, self.body, self.tcx)
+                .ty
+                .is_freeze(self.tcx, self.param_env, self.source_info.span);
+            // prevent
+            // * `&mut x.field`
+            // * `x.field = y;`
+            // * `&x.field` if `field`'s type has interior mutability
+            // because either of these would allow modifying the layout constrained field and
+            // insert values that violate the layout constraints.
+            if context.is_mutating_use() || is_borrow_of_interior_mut {
+                self.check_mut_borrowing_layout_constrained_field(
+                    place, context.is_mutating_use(),
+                );
+            }
+            let old_source_info = self.source_info;
+            if let (PlaceBase::Local(local), []) = (&place.base, proj_base) {
+                if self.body.local_decls[*local].internal {
+                    // Internal locals are used in the `move_val_init` desugaring.
+                    // We want to check unsafety against the source info of the
+                    // desugaring, rather than the source info of the RHS.
+                    self.source_info = self.body.local_decls[*local].source_info;
                 }
-                let old_source_info = self.source_info;
-                if let (PlaceBase::Local(local), None) = (&place.base, &proj.base) {
-                    if self.body.local_decls[*local].internal {
-                        // Internal locals are used in the `move_val_init` desugaring.
-                        // We want to check unsafety against the source info of the
-                        // desugaring, rather than the source info of the RHS.
-                        self.source_info = self.body.local_decls[*local].source_info;
-                    }
+            }
+            let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
+            match base_ty.sty {
+                ty::RawPtr(..) => {
+                    self.require_unsafe("dereference of raw pointer",
+                        "raw pointers may be NULL, dangling or unaligned; they can violate \
+                         aliasing rules and cause data races: all of these are undefined \
+                         behavior", UnsafetyViolationKind::General)
                 }
-                let base_ty = Place::ty_from(&place.base, &proj.base, self.body, self.tcx).ty;
-                match base_ty.sty {
-                    ty::RawPtr(..) => {
-                        self.require_unsafe("dereference of raw pointer",
-                            "raw pointers may be NULL, dangling or unaligned; they can violate \
-                             aliasing rules and cause data races: all of these are undefined \
-                             behavior", UnsafetyViolationKind::General)
-                    }
-                    ty::Adt(adt, _) => {
-                        if adt.is_union() {
-                            if context == PlaceContext::MutatingUse(MutatingUseContext::Store) ||
-                                context == PlaceContext::MutatingUse(MutatingUseContext::Drop) ||
-                                context == PlaceContext::MutatingUse(
-                                    MutatingUseContext::AsmOutput
-                                )
-                            {
-                                let elem_ty = match proj.elem {
-                                    ProjectionElem::Field(_, ty) => ty,
-                                    _ => span_bug!(
-                                        self.source_info.span,
-                                        "non-field projection {:?} from union?",
-                                        place)
-                                };
-                                if !elem_ty.is_copy_modulo_regions(
-                                    self.tcx,
-                                    self.param_env,
+                ty::Adt(adt, _) => {
+                    if adt.is_union() {
+                        if context == PlaceContext::MutatingUse(MutatingUseContext::Store) ||
+                            context == PlaceContext::MutatingUse(MutatingUseContext::Drop) ||
+                            context == PlaceContext::MutatingUse(
+                                MutatingUseContext::AsmOutput
+                            )
+                        {
+                            let elem_ty = match elem {
+                                ProjectionElem::Field(_, ty) => ty,
+                                _ => span_bug!(
                                     self.source_info.span,
-                                ) {
-                                    self.require_unsafe(
-                                        "assignment to non-`Copy` union field",
-                                        "the previous content of the field will be dropped, which \
-                                         causes undefined behavior if the field was not properly \
-                                         initialized", UnsafetyViolationKind::General)
-                                } else {
-                                    // write to non-move union, safe
-                                }
+                                    "non-field projection {:?} from union?",
+                                    place)
+                            };
+                            if !elem_ty.is_copy_modulo_regions(
+                                self.tcx,
+                                self.param_env,
+                                self.source_info.span,
+                            ) {
+                                self.require_unsafe(
+                                    "assignment to non-`Copy` union field",
+                                    "the previous content of the field will be dropped, which \
+                                     causes undefined behavior if the field was not properly \
+                                     initialized", UnsafetyViolationKind::General)
                             } else {
-                                self.require_unsafe("access to union field",
-                                    "the field may not be properly initialized: using \
-                                     uninitialized data will cause undefined behavior",
-                                     UnsafetyViolationKind::General)
+                                // write to non-move union, safe
                             }
+                        } else {
+                            self.require_unsafe("access to union field",
+                                "the field may not be properly initialized: using \
+                                 uninitialized data will cause undefined behavior",
+                                 UnsafetyViolationKind::General)
                         }
                     }
-                    _ => {}
                 }
-                self.source_info = old_source_info;
+                _ => {}
             }
-        });
+            self.source_info = old_source_info;
+        }
     }
 }
 
@@ -407,12 +407,14 @@
         place: &Place<'tcx>,
         is_mut_use: bool,
     ) {
-        let mut projection = &place.projection;
-        while let Some(proj) = projection {
-            match proj.elem {
+        let mut cursor = &*place.projection;
+        while let [proj_base @ .., elem] = cursor {
+            cursor = proj_base;
+
+            match elem {
                 ProjectionElem::Field(..) => {
                     let ty =
-                        Place::ty_from(&place.base, &proj.base, &self.body.local_decls, self.tcx)
+                        Place::ty_from(&place.base, proj_base, &self.body.local_decls, self.tcx)
                             .ty;
                     match ty.sty {
                         ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
@@ -447,7 +449,6 @@
                 }
                 _ => {}
             }
-            projection = &proj.base;
         }
     }
 }
diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs
index ede1cb6..ea17327 100644
--- a/src/librustc_mir/transform/cleanup_post_borrowck.rs
+++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs
@@ -39,7 +39,7 @@
                        location: Location) {
         match statement.kind {
             StatementKind::AscribeUserType(..)
-            | StatementKind::Assign(_, box Rvalue::Ref(_, BorrowKind::Shallow, _))
+            | StatementKind::Assign(box(_, Rvalue::Ref(_, BorrowKind::Shallow, _)))
             | StatementKind::FakeRead(..) => statement.make_nop(),
             _ => (),
         }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index f261fdc..614d5d2 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -282,53 +282,53 @@
 
     fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         trace!("eval_place(place={:?})", place);
-        place.iterate(|place_base, place_projection| {
-            let mut eval = match place_base {
-                PlaceBase::Local(loc) => self.get_const(*loc).clone()?,
-                PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => {
-                    let generics = self.tcx.generics_of(self.source.def_id());
-                    if generics.requires_monomorphization(self.tcx) {
-                        // FIXME: can't handle code with generics
-                        return None;
-                    }
-                    let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
-                    let instance = Instance::new(self.source.def_id(), substs);
-                    let cid = GlobalId {
-                        instance,
-                        promoted: Some(*promoted),
-                    };
-                    let res = self.use_ecx(source_info, |this| {
-                        this.ecx.const_eval_raw(cid)
-                    })?;
-                    trace!("evaluated promoted {:?} to {:?}", promoted, res);
-                    res.into()
+        let mut eval = match place.base {
+            PlaceBase::Local(loc) => self.get_const(loc).clone()?,
+            PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => {
+                let generics = self.tcx.generics_of(self.source.def_id());
+                if generics.requires_monomorphization(self.tcx) {
+                    // FIXME: can't handle code with generics
+                    return None;
                 }
-                _ => return None,
-            };
-
-            for proj in place_projection {
-                match proj.elem {
-                    ProjectionElem::Field(field, _) => {
-                        trace!("field proj on {:?}", proj.base);
-                        eval = self.use_ecx(source_info, |this| {
-                            this.ecx.operand_field(eval, field.index() as u64)
-                        })?;
-                    },
-                    ProjectionElem::Deref => {
-                        trace!("processing deref");
-                        eval = self.use_ecx(source_info, |this| {
-                            this.ecx.deref_operand(eval)
-                        })?.into();
-                    }
-                    // We could get more projections by using e.g., `operand_projection`,
-                    // but we do not even have the stack frame set up properly so
-                    // an `Index` projection would throw us off-track.
-                    _ => return None,
-                }
+                let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
+                let instance = Instance::new(self.source.def_id(), substs);
+                let cid = GlobalId {
+                    instance,
+                    promoted: Some(promoted),
+                };
+                let res = self.use_ecx(source_info, |this| {
+                    this.ecx.const_eval_raw(cid)
+                })?;
+                trace!("evaluated promoted {:?} to {:?}", promoted, res);
+                res.into()
             }
+            _ => return None,
+        };
 
-            Some(eval)
-        })
+        for (i, elem) in place.projection.iter().enumerate() {
+            let proj_base = &place.projection[..i];
+
+            match elem {
+                ProjectionElem::Field(field, _) => {
+                    trace!("field proj on {:?}", proj_base);
+                    eval = self.use_ecx(source_info, |this| {
+                        this.ecx.operand_field(eval, field.index() as u64)
+                    })?;
+                },
+                ProjectionElem::Deref => {
+                    trace!("processing deref");
+                    eval = self.use_ecx(source_info, |this| {
+                        this.ecx.deref_operand(eval)
+                    })?.into();
+                }
+                // We could get more projections by using e.g., `operand_projection`,
+                // but we do not even have the stack frame set up properly so
+                // an `Index` projection would throw us off-track.
+                _ => return None,
+            }
+        }
+
+        Some(eval)
     }
 
     fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
@@ -405,13 +405,16 @@
                 }
 
                 let arg = self.eval_operand(arg, source_info)?;
+                let oflo_check = self.tcx.sess.overflow_checks();
                 let val = self.use_ecx(source_info, |this| {
                     let prim = this.ecx.read_immediate(arg)?;
                     match op {
                         UnOp::Neg => {
-                            // Need to do overflow check here: For actual CTFE, MIR
-                            // generation emits code that does this before calling the op.
-                            if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
+                            // We check overflow in debug mode already
+                            // so should only check in release mode.
+                            if !oflo_check
+                            && prim.layout.ty.is_signed()
+                            && prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
                                 throw_panic!(OverflowNeg)
                             }
                         }
@@ -485,7 +488,9 @@
                         Scalar::from_bool(overflow).into(),
                     )
                 } else {
-                    if overflow {
+                    // We check overflow in debug mode already
+                    // so should only check in release mode.
+                    if !self.tcx.sess.overflow_checks() && overflow {
                         let err = err_panic!(Overflow(op)).into();
                         let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
                         return None;
@@ -660,7 +665,7 @@
         location: Location,
     ) {
         trace!("visit_statement: {:?}", statement);
-        if let StatementKind::Assign(ref place, ref mut rval) = statement.kind {
+        if let StatementKind::Assign(box(ref place, ref mut rval)) = statement.kind {
             let place_ty: Ty<'tcx> = place
                 .ty(&self.local_decls, self.tcx)
                 .ty;
@@ -668,7 +673,7 @@
                 if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
                     if let Place {
                         base: PlaceBase::Local(local),
-                        projection: None,
+                        projection: box [],
                     } = *place {
                         trace!("checking whether {:?} can be stored to {:?}", value, local);
                         if self.can_const_prop[local] {
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index f3a523a..28f97f4 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -94,11 +94,13 @@
                     // That use of the source must be an assignment.
                     match statement.kind {
                         StatementKind::Assign(
-                            Place {
-                                base: PlaceBase::Local(local),
-                                projection: None,
-                            },
-                            box Rvalue::Use(ref operand)
+                            box(
+                                Place {
+                                    base: PlaceBase::Local(local),
+                                    projection: box [],
+                                },
+                                Rvalue::Use(ref operand)
+                            )
                         ) if local == dest_local => {
                             let maybe_action = match *operand {
                                 Operand::Copy(ref src_place) |
@@ -148,24 +150,28 @@
             if let Some(stmt) = body[location.block].statements.get(location.statement_index) {
                 match stmt.kind {
                     StatementKind::Assign(
-                        Place {
-                            base: PlaceBase::Local(local),
-                            projection: None,
-                        },
-                        box Rvalue::Use(Operand::Copy(Place {
-                            base: PlaceBase::Local(src_local),
-                            projection: None,
-                        })),
+                        box(
+                            Place {
+                                base: PlaceBase::Local(local),
+                                projection: box [],
+                            },
+                            Rvalue::Use(Operand::Copy(Place {
+                                base: PlaceBase::Local(src_local),
+                                projection: box [],
+                            })),
+                        )
                     ) |
                     StatementKind::Assign(
-                        Place {
-                            base: PlaceBase::Local(local),
-                            projection: None,
-                        },
-                        box Rvalue::Use(Operand::Move(Place {
-                            base: PlaceBase::Local(src_local),
-                            projection: None,
-                        })),
+                        box(
+                            Place {
+                                base: PlaceBase::Local(local),
+                                projection: box [],
+                            },
+                            Rvalue::Use(Operand::Move(Place {
+                                base: PlaceBase::Local(src_local),
+                                projection: box [],
+                            })),
+                        )
                     ) if local == dest_local && dest_local == src_local => {}
                     _ => {
                         continue;
@@ -194,7 +200,7 @@
         // The source must be a local.
         let src_local = if let Place {
             base: PlaceBase::Local(local),
-            projection: None,
+            projection: box [],
         } = *src_place {
             local
         } else {
@@ -351,11 +357,11 @@
         match *operand {
             Operand::Copy(Place {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: box [],
             }) |
             Operand::Move(Place {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: box [],
             }) if local == self.dest_local => {}
             _ => return,
         }
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs
index 1fc7ce0..c1224be 100644
--- a/src/librustc_mir/transform/deaggregator.rs
+++ b/src/librustc_mir/transform/deaggregator.rs
@@ -12,8 +12,8 @@
         for bb in basic_blocks {
             bb.expand_statements(|stmt| {
                 // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
-                if let StatementKind::Assign(_, ref rhs) = stmt.kind {
-                    if let Rvalue::Aggregate(ref kind, _) = **rhs {
+                if let StatementKind::Assign(box(_, ref rhs)) = stmt.kind {
+                    if let Rvalue::Aggregate(ref kind, _) = *rhs {
                         // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
                         if let AggregateKind::Array(_) = **kind {
                             return None;
@@ -28,7 +28,7 @@
                 let stmt = stmt.replace_nop();
                 let source_info = stmt.source_info;
                 let (lhs, kind, operands) = match stmt.kind {
-                    StatementKind::Assign(lhs, box rvalue) => {
+                    StatementKind::Assign(box(lhs, rvalue)) => {
                         match rvalue {
                             Rvalue::Aggregate(kind, operands) => (lhs, kind, operands),
                             _ => bug!()
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 7a5c00c..a9c66b3 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -236,47 +236,34 @@
     }
 
     fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path> {
-        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
-            match p {
-                &Projection {
-                    elem: ProjectionElem::Field(idx, _), ..
-                } => idx == field,
-                _ => false
-            }
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+            ProjectionElem::Field(idx, _) => *idx == field,
+            _ => false,
         })
     }
 
     fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path> {
-        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
-            match p {
-                &Projection {
-                    elem: ProjectionElem::ConstantIndex{offset, min_length: _, from_end: false}, ..
-                } => offset == index,
-                &Projection {
-                    elem: ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true}, ..
-                } => size - offset == index,
-                _ => false
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: false } => {
+                *offset == index
             }
+            ProjectionElem::ConstantIndex { offset, min_length: _, from_end: true } => {
+                size - offset == index
+            }
+            _ => false,
         })
     }
 
     fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
-        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
-            match p {
-                &Projection { elem: ProjectionElem::Deref, .. } => true,
-                _ => false
-            }
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| {
+            *e == ProjectionElem::Deref
         })
     }
 
     fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path> {
-        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
-            match p {
-                &Projection {
-                    elem: ProjectionElem::Downcast(_, idx), ..
-                } => idx == variant,
-                _ => false
-            }
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+            ProjectionElem::Downcast(_, idx) => *idx == variant,
+            _ => false
         })
     }
 
@@ -465,7 +452,7 @@
         assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported");
 
         let assign = Statement {
-            kind: StatementKind::Assign(location.clone(), box Rvalue::Use(value.clone())),
+            kind: StatementKind::Assign(box(location.clone(), Rvalue::Use(value.clone()))),
             source_info: terminator.source_info
         };
 
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index d873311..caf588a 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -67,7 +67,7 @@
 use crate::transform::simplify;
 use crate::transform::no_landing_pads::no_landing_pads;
 use crate::dataflow::{DataflowResults, DataflowResultsConsumer, FlowAtLocation};
-use crate::dataflow::{do_dataflow, DebugFormatted, state_for_location};
+use crate::dataflow::{do_dataflow, DebugFormatted, DataflowResultsCursor};
 use crate::dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals, RequiresStorage};
 use crate::util::dump_mir;
 use crate::util::liveness;
@@ -107,10 +107,7 @@
         if place.base == PlaceBase::Local(self_arg()) {
             replace_base(place, Place {
                 base: PlaceBase::Local(self_arg()),
-                projection: Some(Box::new(Projection {
-                    base: None,
-                    elem: ProjectionElem::Deref,
-                })),
+                projection: Box::new([ProjectionElem::Deref]),
             });
         } else {
             self.super_place(place, context, location);
@@ -137,10 +134,7 @@
         if place.base == PlaceBase::Local(self_arg()) {
             replace_base(place, Place {
                 base: PlaceBase::Local(self_arg()),
-                projection: Some(Box::new(Projection {
-                    base: None,
-                    elem: ProjectionElem::Field(Field::new(0), self.ref_gen_ty),
-                })),
+                projection: Box::new([ProjectionElem::Field(Field::new(0), self.ref_gen_ty)]),
             });
         } else {
             self.super_place(place, context, location);
@@ -149,13 +143,12 @@
 }
 
 fn replace_base(place: &mut Place<'tcx>, new_base: Place<'tcx>) {
-    let mut projection = &mut place.projection;
-    while let Some(box proj) = projection {
-        projection = &mut proj.base;
-    }
-
     place.base = new_base.base;
-    *projection = new_base.projection;
+
+    let mut new_projection = new_base.projection.to_vec();
+    new_projection.append(&mut place.projection.to_vec());
+
+    place.projection = new_projection.into_boxed_slice();
 }
 
 fn self_arg() -> Local {
@@ -210,13 +203,12 @@
     fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
         let self_place = Place::from(self_arg());
         let base = self_place.downcast_unnamed(variant_index);
-        let field = Projection {
-            base: base.projection,
-            elem: ProjectionElem::Field(Field::new(idx), ty),
-        };
+        let mut projection = base.projection.to_vec();
+        projection.push(ProjectionElem::Field(Field::new(idx), ty));
+
         Place {
             base: base.base,
-            projection: Some(Box::new(field)),
+            projection: projection.into_boxed_slice(),
         }
     }
 
@@ -225,7 +217,10 @@
         let self_place = Place::from(self_arg());
         Statement {
             source_info,
-            kind: StatementKind::SetDiscriminant { place: self_place, variant_index: state_disc },
+            kind: StatementKind::SetDiscriminant {
+                place: box self_place,
+                variant_index: state_disc,
+            },
         }
     }
 
@@ -238,7 +233,7 @@
         let self_place = Place::from(self_arg());
         let assign = Statement {
             source_info: source_info(body),
-            kind: StatementKind::Assign(temp.clone(), box Rvalue::Discriminant(self_place)),
+            kind: StatementKind::Assign(box(temp.clone(), Rvalue::Discriminant(self_place))),
         };
         (assign, temp)
     }
@@ -296,8 +291,12 @@
             // We must assign the value first in case it gets declared dead below
             data.statements.push(Statement {
                 source_info,
-                kind: StatementKind::Assign(Place::RETURN_PLACE,
-                                            box self.make_state(state_idx, v)),
+                kind: StatementKind::Assign(
+                    box(
+                        Place::return_place(),
+                        self.make_state(state_idx, v)
+                    )
+                ),
             });
             let state = if let Some(resume) = resume { // Yield
                 let state = 3 + self.suspension_points.len();
@@ -437,9 +436,10 @@
     // Calculate when MIR locals have live storage. This gives us an upper bound of their
     // lifetimes.
     let storage_live_analysis = MaybeStorageLive::new(body);
-    let storage_live =
+    let storage_live_results =
         do_dataflow(tcx, body, def_id, &[], &dead_unwinds, storage_live_analysis,
                     |bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
+    let mut storage_live_cursor = DataflowResultsCursor::new(&storage_live_results, body);
 
     // Find the MIR locals which do not use StorageLive/StorageDead statements.
     // The storage of these locals are always live.
@@ -449,17 +449,18 @@
     // Calculate the MIR locals which have been previously
     // borrowed (even if they are still active).
     let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body);
-    let borrowed_locals_result =
+    let borrowed_locals_results =
         do_dataflow(tcx, body, def_id, &[], &dead_unwinds, borrowed_locals_analysis,
                     |bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
+    let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body);
 
     // Calculate the MIR locals that we actually need to keep storage around
     // for.
-    let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result);
-    let requires_storage =
+    let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_results);
+    let requires_storage_results =
         do_dataflow(tcx, body, def_id, &[], &dead_unwinds, requires_storage_analysis,
                     |bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
-    let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result);
+    let mut requires_storage_cursor = DataflowResultsCursor::new(&requires_storage_results, body);
 
     // Calculate the liveness of MIR locals ignoring borrows.
     let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len());
@@ -485,10 +486,6 @@
             };
 
             if !movable {
-                let borrowed_locals = state_for_location(loc,
-                                                         &borrowed_locals_analysis,
-                                                         &borrowed_locals_result,
-                                                         body);
                 // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
                 // This is correct for movable generators since borrows cannot live across
                 // suspension points. However for immovable generators we need to account for
@@ -499,22 +496,19 @@
                 // If a borrow is converted to a raw reference, we must also assume that it lives
                 // forever. Note that the final liveness is still bounded by the storage liveness
                 // of the local, which happens using the `intersect` operation below.
-                liveness.outs[block].union(&borrowed_locals);
+                borrowed_locals_cursor.seek(loc);
+                liveness.outs[block].union(borrowed_locals_cursor.get());
             }
 
-            let storage_liveness = state_for_location(loc,
-                                                      &storage_live_analysis,
-                                                      &storage_live,
-                                                      body);
+            storage_live_cursor.seek(loc);
+            let storage_liveness = storage_live_cursor.get();
 
             // Store the storage liveness for later use so we can restore the state
             // after a suspension point
             storage_liveness_map.insert(block, storage_liveness.clone());
 
-            let mut storage_required = state_for_location(loc,
-                                                          &requires_storage_analysis,
-                                                          &requires_storage,
-                                                          body);
+            requires_storage_cursor.seek(loc);
+            let mut storage_required = requires_storage_cursor.get().clone();
 
             // Mark locals without storage statements as always requiring storage
             storage_required.union(&ignored.0);
@@ -550,8 +544,7 @@
         body,
         &live_locals,
         &ignored,
-        requires_storage,
-        requires_storage_analysis);
+        requires_storage_results);
 
     LivenessInfo {
         live_locals,
@@ -589,7 +582,6 @@
     stored_locals: &liveness::LiveVarSet,
     ignored: &StorageIgnored,
     requires_storage: DataflowResults<'tcx, RequiresStorage<'mir, 'tcx>>,
-    _requires_storage_analysis: RequiresStorage<'mir, 'tcx>,
 ) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
     assert_eq!(body.local_decls.len(), ignored.0.domain_size());
     assert_eq!(body.local_decls.len(), stored_locals.domain_size());
@@ -848,7 +840,7 @@
                 kind: TerminatorKind::Drop {
                     location: Place {
                         base: PlaceBase::Local(local),
-                        projection: None,
+                        projection: box [],
                     },
                     target,
                     unwind
@@ -937,7 +929,7 @@
         // Alias tracking must know we changed the type
         body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
             source_info,
-            kind: StatementKind::Retag(RetagKind::Raw, Place::from(self_arg())),
+            kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())),
         })
     }
 
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index f31303c..5ad026d 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -425,22 +425,20 @@
                 // writes to `i`. To prevent this we need to create a temporary
                 // borrow of the place and pass the destination as `*temp` instead.
                 fn dest_needs_borrow(place: &Place<'_>) -> bool {
-                    place.iterate(|place_base, place_projection| {
-                        for proj in place_projection {
-                            match proj.elem {
-                                ProjectionElem::Deref |
-                                ProjectionElem::Index(_) => return true,
-                                _ => {}
-                            }
+                    for elem in place.projection.iter() {
+                        match elem {
+                            ProjectionElem::Deref |
+                            ProjectionElem::Index(_) => return true,
+                            _ => {}
                         }
+                    }
 
-                        match place_base {
-                            // Static variables need a borrow because the callee
-                            // might modify the same static.
-                            PlaceBase::Static(_) => true,
-                            _ => false
-                        }
-                    })
+                    match place.base {
+                        // Static variables need a borrow because the callee
+                        // might modify the same static.
+                        PlaceBase::Static(_) => true,
+                        _ => false
+                    }
                 }
 
                 let dest = if dest_needs_borrow(&destination.0) {
@@ -459,7 +457,7 @@
 
                     let stmt = Statement {
                         source_info: callsite.location,
-                        kind: StatementKind::Assign(tmp.clone(), box dest)
+                        kind: StatementKind::Assign(box(tmp.clone(), dest))
                     };
                     caller_body[callsite.bb]
                         .statements.push(stmt);
@@ -591,7 +589,7 @@
 
         if let Operand::Move(Place {
             base: PlaceBase::Local(local),
-            projection: None,
+            projection: box [],
         }) = arg {
             if caller_body.local_kind(local) == LocalKind::Temp {
                 // Reuse the operand if it's a temporary already
@@ -610,7 +608,7 @@
 
         let stmt = Statement {
             source_info: callsite.location,
-            kind: StatementKind::Assign(Place::from(arg_tmp), box arg),
+            kind: StatementKind::Assign(box(Place::from(arg_tmp), arg)),
         };
         caller_body[callsite.bb].statements.push(stmt);
         arg_tmp
@@ -660,7 +658,7 @@
             match self.destination {
                 Place {
                     base: PlaceBase::Local(l),
-                    projection: None,
+                    projection: box [],
                 } => {
                     *local = l;
                     return;
@@ -684,7 +682,7 @@
         match place {
             Place {
                 base: PlaceBase::Local(RETURN_PLACE),
-                projection: None,
+                projection: box [],
             } => {
                 // Return pointer; update the place itself
                 *place = self.destination.clone();
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index abe4160..0e04e63 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -43,12 +43,21 @@
             let new_place = match *rvalue {
                 Rvalue::Ref(_, _, Place {
                     ref mut base,
-                    projection: Some(ref mut projection),
-                }) => Place {
-                    // Replace with dummy
-                    base: mem::replace(base, PlaceBase::Local(Local::new(0))),
-                    projection: projection.base.take(),
-                },
+                    projection: ref mut projection @ box [.., _],
+                }) => {
+                    if let box [proj_l @ .., proj_r] = projection {
+                        let place = Place {
+                            // Replace with dummy
+                            base: mem::replace(base, PlaceBase::Local(Local::new(0))),
+                            projection: proj_l.to_vec().into_boxed_slice(),
+                        };
+                        *projection = vec![proj_r.clone()].into_boxed_slice();
+
+                        place
+                    } else {
+                        unreachable!();
+                    }
+                }
                 _ => bug!("Detected `&*` but didn't find `&*`!"),
             };
             *rvalue = Rvalue::Use(Operand::Copy(new_place))
@@ -83,13 +92,11 @@
 impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         if let Rvalue::Ref(_, _, Place {
-            ref base,
-            projection: Some(ref projection),
-        }) = *rvalue {
-            if let ProjectionElem::Deref = projection.elem {
-                if Place::ty_from(&base, &projection.base, self.body, self.tcx).ty.is_region_ptr() {
-                    self.optimizations.and_stars.insert(location);
-                }
+            base,
+            projection: box [proj_base @ .., ProjectionElem::Deref],
+        }) = rvalue {
+            if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() {
+                self.optimizations.and_stars.insert(location);
             }
         }
 
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index cdccdfe..7d1b96b 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -187,7 +187,7 @@
                 span,
                 scope: OUTERMOST_SOURCE_SCOPE
             },
-            kind: StatementKind::Assign(Place::from(dest), box rvalue)
+            kind: StatementKind::Assign(box(Place::from(dest), rvalue))
         });
     }
 
@@ -222,10 +222,10 @@
         // First, take the Rvalue or Call out of the source MIR,
         // or duplicate it, depending on keep_original.
         if loc.statement_index < no_stmts {
-            let (rvalue, source_info) = {
+            let (mut rvalue, source_info) = {
                 let statement = &mut self.source[loc.block].statements[loc.statement_index];
                 let rhs = match statement.kind {
-                    StatementKind::Assign(_, ref mut rhs) => rhs,
+                    StatementKind::Assign(box(_, ref mut rhs)) => rhs,
                     _ => {
                         span_bug!(statement.source_info.span, "{:?} is not an assignment",
                                   statement);
@@ -235,12 +235,11 @@
                 (if self.keep_original {
                     rhs.clone()
                 } else {
-                    let unit = box Rvalue::Aggregate(box AggregateKind::Tuple, vec![]);
+                    let unit = Rvalue::Aggregate(box AggregateKind::Tuple, vec![]);
                     mem::replace(rhs, unit)
                 }, statement.source_info)
             };
 
-            let mut rvalue = *rvalue;
             self.visit_rvalue(&mut rvalue, loc);
             self.assign(new_temp, rvalue, source_info.span);
         } else {
@@ -318,7 +317,7 @@
                         ty,
                         def_id,
                     }),
-                    projection: None,
+                    projection: box [],
                 }
             };
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
@@ -326,7 +325,7 @@
                 Candidate::Ref(loc) => {
                     let ref mut statement = blocks[loc.block].statements[loc.statement_index];
                     match statement.kind {
-                        StatementKind::Assign(_, box Rvalue::Ref(_, _, ref mut place)) => {
+                        StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref mut place))) => {
                             // Use the underlying local for this (necessarily interior) borrow.
                             let ty = place.base.ty(local_decls).ty;
                             let span = statement.source_info.span;
@@ -334,9 +333,9 @@
                             Operand::Move(Place {
                                 base: mem::replace(
                                     &mut place.base,
-                                    promoted_place(ty, span).base
+                                    promoted_place(ty, span).base,
                                 ),
-                                projection: None,
+                                projection: box [],
                             })
                         }
                         _ => bug!()
@@ -345,7 +344,7 @@
                 Candidate::Repeat(loc) => {
                     let ref mut statement = blocks[loc.block].statements[loc.statement_index];
                     match statement.kind {
-                        StatementKind::Assign(_, box Rvalue::Repeat(ref mut operand, _)) => {
+                        StatementKind::Assign(box(_, Rvalue::Repeat(ref mut operand, _))) => {
                             let ty = operand.ty(local_decls, self.tcx);
                             let span = statement.source_info.span;
                             mem::replace(
@@ -420,10 +419,10 @@
             Candidate::Repeat(Location { block, statement_index }) |
             Candidate::Ref(Location { block, statement_index }) => {
                 match body[block].statements[statement_index].kind {
-                    StatementKind::Assign(Place {
+                    StatementKind::Assign(box(Place {
                         base: PlaceBase::Local(local),
-                        projection: None,
-                    }, _) => {
+                        projection: box [],
+                    }, _)) => {
                         if temps[local] == TempState::PromotedOut {
                             // Already promoted.
                             continue;
@@ -473,10 +472,10 @@
     for block in body.basic_blocks_mut() {
         block.statements.retain(|statement| {
             match statement.kind {
-                StatementKind::Assign(Place {
+                StatementKind::Assign(box(Place {
                     base: PlaceBase::Local(index),
-                    projection: None,
-                }, _) |
+                    projection: box [],
+                }, _)) |
                 StatementKind::StorageLive(index) |
                 StatementKind::StorageDead(index) => {
                     !promoted(index)
@@ -488,7 +487,7 @@
         match terminator.kind {
             TerminatorKind::Drop { location: Place {
                 base: PlaceBase::Local(index),
-                projection: None,
+                projection: box [],
             }, target, .. } => {
                 if promoted(index) {
                     terminator.kind = TerminatorKind::Goto {
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index a77421c..7cc1e63 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -25,11 +25,13 @@
 use syntax::symbol::sym;
 use syntax_pos::{Span, DUMMY_SP};
 
+use std::borrow::Cow;
 use std::cell::Cell;
 use std::fmt;
 use std::ops::{Deref, Index, IndexMut};
 use std::usize;
 
+use rustc::hir::HirId;
 use crate::transform::{MirPass, MirSource};
 use super::promote_consts::{self, Candidate, TempState};
 
@@ -185,26 +187,28 @@
         cx: &ConstCx<'_, 'tcx>,
         place: PlaceRef<'_, 'tcx>,
     ) -> bool {
-        let proj = place.projection.as_ref().unwrap();
+        if let [proj_base @ .., elem] = place.projection {
+            let base_qualif = Self::in_place(cx, PlaceRef {
+                base: place.base,
+                projection: proj_base,
+            });
+            let qualif = base_qualif && Self::mask_for_ty(
+                cx,
+                Place::ty_from(place.base, proj_base, cx.body, cx.tcx)
+                    .projection_ty(cx.tcx, elem)
+                    .ty,
+            );
+            match elem {
+                ProjectionElem::Deref |
+                ProjectionElem::Subslice { .. } |
+                ProjectionElem::Field(..) |
+                ProjectionElem::ConstantIndex { .. } |
+                ProjectionElem::Downcast(..) => qualif,
 
-        let base_qualif = Self::in_place(cx, PlaceRef {
-            base: place.base,
-            projection: &proj.base,
-        });
-        let qualif = base_qualif && Self::mask_for_ty(
-            cx,
-            Place::ty_from(place.base, &proj.base, cx.body, cx.tcx)
-                .projection_ty(cx.tcx, &proj.elem)
-                .ty,
-        );
-        match proj.elem {
-            ProjectionElem::Deref |
-            ProjectionElem::Subslice { .. } |
-            ProjectionElem::Field(..) |
-            ProjectionElem::ConstantIndex { .. } |
-            ProjectionElem::Downcast(..) => qualif,
-
-            ProjectionElem::Index(local) => qualif || Self::in_local(cx, local),
+                ProjectionElem::Index(local) => qualif || Self::in_local(cx, *local),
+            }
+        } else {
+            bug!("This should be called if projection is not empty");
         }
     }
 
@@ -219,24 +223,24 @@
         match place {
             PlaceRef {
                 base: PlaceBase::Local(local),
-                projection: None,
+                projection: [],
             } => Self::in_local(cx, *local),
             PlaceRef {
                 base: PlaceBase::Static(box Static {
                     kind: StaticKind::Promoted(..),
                     ..
                 }),
-                projection: None,
+                projection: [],
             } => bug!("qualifying already promoted MIR"),
             PlaceRef {
                 base: PlaceBase::Static(static_),
-                projection: None,
+                projection: [],
             } => {
                 Self::in_static(cx, static_)
             },
             PlaceRef {
                 base: _,
-                projection: Some(_),
+                projection: [.., _],
             } => Self::in_projection(cx, place),
         }
     }
@@ -287,13 +291,13 @@
 
             Rvalue::Ref(_, _, ref place) => {
                 // Special-case reborrows to be more like a copy of the reference.
-                if let Some(ref proj) = place.projection {
-                    if let ProjectionElem::Deref = proj.elem {
-                        let base_ty = Place::ty_from(&place.base, &proj.base, cx.body, cx.tcx).ty;
+                if let box [proj_base @ .., elem] = &place.projection {
+                    if ProjectionElem::Deref == *elem {
+                        let base_ty = Place::ty_from(&place.base, proj_base, cx.body, cx.tcx).ty;
                         if let ty::Ref(..) = base_ty.sty {
                             return Self::in_place(cx, PlaceRef {
                                 base: &place.base,
-                                projection: &proj.base,
+                                projection: proj_base,
                             });
                         }
                     }
@@ -451,30 +455,32 @@
         cx: &ConstCx<'_, 'tcx>,
         place: PlaceRef<'_, 'tcx>,
     ) -> bool {
-        let proj = place.projection.as_ref().unwrap();
+        if let [proj_base @ .., elem] = place.projection {
+            match elem {
+                ProjectionElem::Deref |
+                ProjectionElem::Downcast(..) => return true,
 
-        match proj.elem {
-            ProjectionElem::Deref |
-            ProjectionElem::Downcast(..) => return true,
+                ProjectionElem::ConstantIndex {..} |
+                ProjectionElem::Subslice {..} |
+                ProjectionElem::Index(_) => {}
 
-            ProjectionElem::ConstantIndex {..} |
-            ProjectionElem::Subslice {..} |
-            ProjectionElem::Index(_) => {}
-
-            ProjectionElem::Field(..) => {
-                if cx.mode == Mode::NonConstFn {
-                    let base_ty = Place::ty_from(place.base, &proj.base, cx.body, cx.tcx).ty;
-                    if let Some(def) = base_ty.ty_adt_def() {
-                        // No promotion of union field accesses.
-                        if def.is_union() {
-                            return true;
+                ProjectionElem::Field(..) => {
+                    if cx.mode == Mode::NonConstFn {
+                        let base_ty = Place::ty_from(place.base, proj_base, cx.body, cx.tcx).ty;
+                        if let Some(def) = base_ty.ty_adt_def() {
+                            // No promotion of union field accesses.
+                            if def.is_union() {
+                                return true;
+                            }
                         }
                     }
                 }
             }
-        }
 
-        Self::in_projection_structurally(cx, place)
+            Self::in_projection_structurally(cx, place)
+        } else {
+            bug!("This should be called if projection is not empty");
+        }
     }
 
     fn in_rvalue(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool {
@@ -804,23 +810,18 @@
                     // We might have a candidate for promotion.
                     let candidate = Candidate::Ref(location);
                     // Start by traversing to the "base", with non-deref projections removed.
-                    let mut place_projection = &place.projection;
-                    while let Some(proj) = place_projection {
-                        if proj.elem == ProjectionElem::Deref {
-                            break;
-                        }
-                        place_projection = &proj.base;
-                    }
+                    let deref_proj =
+                        place.projection.iter().rev().find(|&elem| *elem == ProjectionElem::Deref);
 
                     debug!(
                         "qualify_consts: promotion candidate: place={:?} {:?}",
-                        place.base, place_projection
+                        place.base, deref_proj
                     );
                     // We can only promote interior borrows of promotable temps (non-temps
                     // don't get promoted anyway).
                     // (If we bailed out of the loop due to a `Deref` above, we will definitely
                     // not enter the conditional here.)
-                    if let (PlaceBase::Local(local), None) = (&place.base, place_projection) {
+                    if let (PlaceBase::Local(local), None) = (&place.base, deref_proj) {
                         if self.body.local_kind(*local) == LocalKind::Temp {
                             debug!("qualify_consts: promotion candidate: local={:?}", local);
                             // The borrowed place doesn't have `HasMutInterior`
@@ -856,27 +857,27 @@
             _ => {},
         }
 
-        let mut dest_projection = &dest.projection;
+        let mut dest_projection = &dest.projection[..];
         let index = loop {
             match (&dest.base, dest_projection) {
                 // We treat all locals equal in constants
-                (&PlaceBase::Local(index), None) => break index,
+                (&PlaceBase::Local(index), []) => break index,
                 // projections are transparent for assignments
                 // we qualify the entire destination at once, even if just a field would have
                 // stricter qualification
-                (base, Some(proj)) => {
+                (base, [proj_base @ .., _]) => {
                     // Catch more errors in the destination. `visit_place` also checks various
                     // projection rules like union field access and raw pointer deref
                     let context = PlaceContext::MutatingUse(MutatingUseContext::Store);
                     self.visit_place_base(base, context, location);
-                    self.visit_projection(base, proj, context, location);
-                    dest_projection = &proj.base;
+                    self.visit_projection(base, dest_projection, context, location);
+                    dest_projection = proj_base;
                 },
                 (&PlaceBase::Static(box Static {
                     kind: StaticKind::Promoted(..),
                     ..
-                }), None) => bug!("promoteds don't exist yet during promotion"),
-                (&PlaceBase::Static(box Static{ kind: _, .. }), None) => {
+                }), []) => bug!("promoteds don't exist yet during promotion"),
+                (&PlaceBase::Static(box Static{ kind: _, .. }), []) => {
                     // Catch more errors in the destination. `visit_place` also checks that we
                     // do not try to access statics from constants or try to mutate statics
                     let context = PlaceContext::MutatingUse(MutatingUseContext::Store);
@@ -981,23 +982,25 @@
         for candidate in &self.promotion_candidates {
             match *candidate {
                 Candidate::Repeat(Location { block: bb, statement_index: stmt_idx }) => {
-                    if let StatementKind::Assign(_, box Rvalue::Repeat(
+                    if let StatementKind::Assign(box(_, Rvalue::Repeat(
                         Operand::Move(Place {
                             base: PlaceBase::Local(index),
-                            projection: None,
+                            projection: box [],
                         }),
                         _
-                    )) = self.body[bb].statements[stmt_idx].kind {
+                    ))) = self.body[bb].statements[stmt_idx].kind {
                         promoted_temps.insert(index);
                     }
                 }
                 Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
                     if let StatementKind::Assign(
-                        _,
-                        box Rvalue::Ref(_, _, Place {
-                            base: PlaceBase::Local(index),
-                            projection: None,
-                        })
+                        box(
+                            _,
+                            Rvalue::Ref(_, _, Place {
+                                base: PlaceBase::Local(index),
+                                projection: box [],
+                            })
+                        )
                     ) = self.body[bb].statements[stmt_idx].kind {
                         promoted_temps.insert(index);
                     }
@@ -1082,7 +1085,7 @@
     fn visit_projection(
         &mut self,
         place_base: &PlaceBase<'tcx>,
-        proj: &Projection<'tcx>,
+        proj: &[PlaceElem<'tcx>],
         context: PlaceContext,
         location: Location,
     ) {
@@ -1091,62 +1094,65 @@
             proj, context, location,
         );
         self.super_projection(place_base, proj, context, location);
-        match proj.elem {
-            ProjectionElem::Deref => {
-                if context.is_mutating_use() {
-                    // `not_const` errors out in const contexts
-                    self.not_const()
-                }
-                let base_ty = Place::ty_from(place_base, &proj.base, self.body, self.tcx).ty;
-                match self.mode {
-                    Mode::NonConstFn => {},
-                    _ => {
-                        if let ty::RawPtr(_) = base_ty.sty {
-                            if !self.tcx.features().const_raw_ptr_deref {
-                                emit_feature_err(
-                                    &self.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
-                                    self.span, GateIssue::Language,
-                                    &format!(
-                                        "dereferencing raw pointers in {}s is unstable",
-                                        self.mode,
-                                    ),
-                                );
+
+        if let [proj_base @ .., elem] = proj {
+            match elem {
+                ProjectionElem::Deref => {
+                    if context.is_mutating_use() {
+                        // `not_const` errors out in const contexts
+                        self.not_const()
+                    }
+                    let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
+                    match self.mode {
+                        Mode::NonConstFn => {},
+                        _ => {
+                            if let ty::RawPtr(_) = base_ty.sty {
+                                if !self.tcx.features().const_raw_ptr_deref {
+                                    emit_feature_err(
+                                        &self.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
+                                        self.span, GateIssue::Language,
+                                        &format!(
+                                            "dereferencing raw pointers in {}s is unstable",
+                                            self.mode,
+                                        ),
+                                    );
+                                }
                             }
                         }
                     }
                 }
-            }
 
-            ProjectionElem::ConstantIndex {..} |
-            ProjectionElem::Subslice {..} |
-            ProjectionElem::Field(..) |
-            ProjectionElem::Index(_) => {
-                let base_ty = Place::ty_from(place_base, &proj.base, self.body, self.tcx).ty;
-                if let Some(def) = base_ty.ty_adt_def() {
-                    if def.is_union() {
-                        match self.mode {
-                            Mode::ConstFn => {
-                                if !self.tcx.features().const_fn_union {
-                                    emit_feature_err(
-                                        &self.tcx.sess.parse_sess, sym::const_fn_union,
-                                        self.span, GateIssue::Language,
-                                        "unions in const fn are unstable",
-                                    );
-                                }
-                            },
+                ProjectionElem::ConstantIndex {..} |
+                ProjectionElem::Subslice {..} |
+                ProjectionElem::Field(..) |
+                ProjectionElem::Index(_) => {
+                    let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
+                    if let Some(def) = base_ty.ty_adt_def() {
+                        if def.is_union() {
+                            match self.mode {
+                                Mode::ConstFn => {
+                                    if !self.tcx.features().const_fn_union {
+                                        emit_feature_err(
+                                            &self.tcx.sess.parse_sess, sym::const_fn_union,
+                                            self.span, GateIssue::Language,
+                                            "unions in const fn are unstable",
+                                        );
+                                    }
+                                },
 
-                            | Mode::NonConstFn
-                            | Mode::Static
-                            | Mode::StaticMut
-                            | Mode::Const
-                            => {},
+                                | Mode::NonConstFn
+                                | Mode::Static
+                                | Mode::StaticMut
+                                | Mode::Const
+                                => {},
+                            }
                         }
                     }
                 }
-            }
 
-            ProjectionElem::Downcast(..) => {
-                self.not_const()
+                ProjectionElem::Downcast(..) => {
+                    self.not_const()
+                }
             }
         }
     }
@@ -1160,7 +1166,7 @@
                 // Mark the consumed locals to indicate later drops are noops.
                 if let Place {
                     base: PlaceBase::Local(local),
-                    projection: None,
+                    projection: box [],
                 } = *place {
                     self.cx.per_local[NeedsDrop].remove(local);
                 }
@@ -1177,11 +1183,11 @@
         if let Rvalue::Ref(_, kind, ref place) = *rvalue {
             // Special-case reborrows.
             let mut reborrow_place = None;
-            if let Some(ref proj) = place.projection {
-                if let ProjectionElem::Deref = proj.elem {
-                    let base_ty = Place::ty_from(&place.base, &proj.base, self.body, self.tcx).ty;
+            if let box [proj_base @ .., elem] = &place.projection {
+                if *elem == ProjectionElem::Deref {
+                    let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.sty {
-                        reborrow_place = Some(&proj.base);
+                        reborrow_place = Some(proj_base);
                     }
                 }
             }
@@ -1202,9 +1208,7 @@
                     ),
                 };
                 self.visit_place_base(&place.base, ctx, location);
-                if let Some(proj) = proj {
-                    self.visit_projection(&place.base, proj, ctx, location);
-                }
+                self.visit_projection(&place.base, proj, ctx, location);
             } else {
                 self.super_rvalue(rvalue, location);
             }
@@ -1475,7 +1479,7 @@
                 // conservatively, that drop elaboration will do.
                 let needs_drop = if let Place {
                     base: PlaceBase::Local(local),
-                    projection: None,
+                    projection: box [],
                 } = *place {
                     if NeedsDrop::in_local(self, local) {
                         Some(self.body.local_decls[local].source_info.span)
@@ -1596,51 +1600,24 @@
         }
 
         let def_id = src.def_id();
-        let id = tcx.hir().as_local_hir_id(def_id).unwrap();
-        let mut const_promoted_temps = None;
-        let mode = match tcx.hir().body_owner_kind(id) {
-            hir::BodyOwnerKind::Closure => Mode::NonConstFn,
-            hir::BodyOwnerKind::Fn => {
-                if tcx.is_const_fn(def_id) {
-                    Mode::ConstFn
-                } else {
-                    Mode::NonConstFn
-                }
-            }
-            hir::BodyOwnerKind::Const => {
-                const_promoted_temps = Some(tcx.mir_const_qualif(def_id).1);
-                Mode::Const
-            }
-            hir::BodyOwnerKind::Static(hir::MutImmutable) => Mode::Static,
-            hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut,
-        };
+        let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
+
+        let mode = determine_mode(tcx, hir_id, def_id);
 
         debug!("run_pass: mode={:?}", mode);
-        if mode == Mode::NonConstFn || mode == Mode::ConstFn {
+        if let Mode::NonConstFn | Mode::ConstFn = mode {
             // This is ugly because Checker holds onto mir,
             // which can't be mutated until its scope ends.
             let (temps, candidates) = {
                 let mut checker = Checker::new(tcx, def_id, body, mode);
-                if mode == Mode::ConstFn {
+                if let Mode::ConstFn = mode {
                     if tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
                         checker.check_const();
                     } else if tcx.is_min_const_fn(def_id) {
-                        // enforce `min_const_fn` for stable const fns
+                        // Enforce `min_const_fn` for stable `const fn`s.
                         use super::qualify_min_const_fn::is_min_const_fn;
                         if let Err((span, err)) = is_min_const_fn(tcx, def_id, body) {
-                            let mut diag = struct_span_err!(
-                                tcx.sess,
-                                span,
-                                E0723,
-                                "{}",
-                                err,
-                            );
-                            diag.note("for more information, see issue \
-                                       https://github.com/rust-lang/rust/issues/57563");
-                            diag.help(
-                                "add `#![feature(const_fn)]` to the crate attributes to enable",
-                            );
-                            diag.emit();
+                            error_min_const_fn_violation(tcx, span, err);
                         } else {
                             // this should not produce any errors, but better safe than sorry
                             // FIXME(#53819)
@@ -1664,107 +1641,119 @@
                 promote_consts::promote_candidates(def_id, body, tcx, temps, candidates)
             );
         } else {
-            if !body.control_flow_destroyed.is_empty() {
-                let mut locals = body.vars_iter();
-                if let Some(local) = locals.next() {
-                    let span = body.local_decls[local].source_info.span;
-                    let mut error = tcx.sess.struct_span_err(
-                        span,
-                        &format!(
-                            "new features like let bindings are not permitted in {}s \
-                            which also use short circuiting operators",
-                            mode,
-                        ),
-                    );
-                    for (span, kind) in body.control_flow_destroyed.iter() {
-                        error.span_note(
-                            *span,
-                            &format!("use of {} here does not actually short circuit due to \
-                            the const evaluator presently not being able to do control flow. \
-                            See https://github.com/rust-lang/rust/issues/49146 for more \
-                            information.", kind),
-                        );
-                    }
-                    for local in locals {
-                        let span = body.local_decls[local].source_info.span;
-                        error.span_note(
-                            span,
-                            "more locals defined here",
-                        );
-                    }
-                    error.emit();
-                }
-            }
-            let promoted_temps = if mode == Mode::Const {
-                // Already computed by `mir_const_qualif`.
-                const_promoted_temps.unwrap()
-            } else {
-                Checker::new(tcx, def_id, body, mode).check_const().1
-            };
+            check_short_circuiting_in_const_local(tcx, body, mode);
 
-            // In `const` and `static` everything without `StorageDead`
-            // is `'static`, we don't have to create promoted MIR fragments,
-            // just remove `Drop` and `StorageDead` on "promoted" locals.
-            debug!("run_pass: promoted_temps={:?}", promoted_temps);
-            for block in body.basic_blocks_mut() {
-                block.statements.retain(|statement| {
-                    match statement.kind {
-                        StatementKind::StorageDead(index) => {
-                            !promoted_temps.contains(index)
-                        }
-                        _ => true
-                    }
-                });
-                let terminator = block.terminator_mut();
-                match terminator.kind {
-                    TerminatorKind::Drop {
-                        location: Place {
-                            base: PlaceBase::Local(index),
-                            projection: None,
-                        },
-                        target,
-                        ..
-                    } => {
-                        if promoted_temps.contains(index) {
-                            terminator.kind = TerminatorKind::Goto {
-                                target,
-                            };
-                        }
-                    }
-                    _ => {}
-                }
-            }
+            let promoted_temps = match mode {
+                Mode::Const => tcx.mir_const_qualif(def_id).1,
+                _ => Checker::new(tcx, def_id, body, mode).check_const().1,
+            };
+            remove_drop_and_storage_dead_on_promoted_locals(body, promoted_temps);
         }
 
-        // Statics must be Sync.
-        if mode == Mode::Static {
-            // `#[thread_local]` statics don't have to be `Sync`.
-            for attr in &tcx.get_attrs(def_id)[..] {
-                if attr.check_name(sym::thread_local) {
-                    return;
-                }
-            }
-            let ty = body.return_ty();
-            tcx.infer_ctxt().enter(|infcx| {
-                let param_env = ty::ParamEnv::empty();
-                let cause = traits::ObligationCause::new(body.span, id, traits::SharedStatic);
-                let mut fulfillment_cx = traits::FulfillmentContext::new();
-                fulfillment_cx.register_bound(&infcx,
-                                              param_env,
-                                              ty,
-                                              tcx.require_lang_item(
-                                                  lang_items::SyncTraitLangItem,
-                                                  Some(body.span)
-                                              ),
-                                              cause);
-                if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-                    infcx.report_fulfillment_errors(&err, None, false);
-                }
-            });
+        if mode == Mode::Static && !tcx.has_attr(def_id, sym::thread_local) {
+            // `static`s (not `static mut`s) which are not `#[thread_local]` must be `Sync`.
+            check_static_is_sync(tcx, body, hir_id);
         }
     }
 }
 
+fn determine_mode(tcx: TyCtxt<'_>, hir_id: HirId, def_id: DefId) -> Mode {
+    match tcx.hir().body_owner_kind(hir_id) {
+        hir::BodyOwnerKind::Closure => Mode::NonConstFn,
+        hir::BodyOwnerKind::Fn if tcx.is_const_fn(def_id) => Mode::ConstFn,
+        hir::BodyOwnerKind::Fn => Mode::NonConstFn,
+        hir::BodyOwnerKind::Const => Mode::Const,
+        hir::BodyOwnerKind::Static(hir::MutImmutable) => Mode::Static,
+        hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut,
+    }
+}
+
+fn error_min_const_fn_violation(tcx: TyCtxt<'_>, span: Span, msg: Cow<'_, str>) {
+    struct_span_err!(tcx.sess, span, E0723, "{}", msg)
+        .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")
+        .emit();
+}
+
+fn check_short_circuiting_in_const_local(tcx: TyCtxt<'_>, body: &mut Body<'tcx>, mode: Mode) {
+    if body.control_flow_destroyed.is_empty() {
+        return;
+    }
+
+    let mut locals = body.vars_iter();
+    if let Some(local) = locals.next() {
+        let span = body.local_decls[local].source_info.span;
+        let mut error = tcx.sess.struct_span_err(
+            span,
+            &format!(
+                "new features like let bindings are not permitted in {}s \
+                which also use short circuiting operators",
+                mode,
+            ),
+        );
+        for (span, kind) in body.control_flow_destroyed.iter() {
+            error.span_note(
+                *span,
+                &format!("use of {} here does not actually short circuit due to \
+                the const evaluator presently not being able to do control flow. \
+                See https://github.com/rust-lang/rust/issues/49146 for more \
+                information.", kind),
+            );
+        }
+        for local in locals {
+            let span = body.local_decls[local].source_info.span;
+            error.span_note(span, "more locals defined here");
+        }
+        error.emit();
+    }
+}
+
+/// In `const` and `static` everything without `StorageDead`
+/// is `'static`, we don't have to create promoted MIR fragments,
+/// just remove `Drop` and `StorageDead` on "promoted" locals.
+fn remove_drop_and_storage_dead_on_promoted_locals(
+    body: &mut Body<'tcx>,
+    promoted_temps: &BitSet<Local>,
+) {
+    debug!("run_pass: promoted_temps={:?}", promoted_temps);
+
+    for block in body.basic_blocks_mut() {
+        block.statements.retain(|statement| {
+            match statement.kind {
+                StatementKind::StorageDead(index) => !promoted_temps.contains(index),
+                _ => true
+            }
+        });
+        let terminator = block.terminator_mut();
+        match terminator.kind {
+            TerminatorKind::Drop {
+                location: Place {
+                    base: PlaceBase::Local(index),
+                    projection: box [],
+                },
+                target,
+                ..
+            } if promoted_temps.contains(index) => {
+                terminator.kind = TerminatorKind::Goto { target };
+            }
+            _ => {}
+        }
+    }
+}
+
+fn check_static_is_sync(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, hir_id: HirId) {
+    let ty = body.return_ty();
+    tcx.infer_ctxt().enter(|infcx| {
+        let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic);
+        let mut fulfillment_cx = traits::FulfillmentContext::new();
+        let sync_def_id = tcx.require_lang_item(lang_items::SyncTraitLangItem, Some(body.span));
+        fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause);
+        if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
+            infcx.report_fulfillment_errors(&err, None, false);
+        }
+    });
+}
+
 fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<FxHashSet<usize>> {
     let attrs = tcx.get_attrs(def_id);
     let attr = attrs.iter().find(|a| a.check_name(sym::rustc_args_required_const))?;
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 5609352..80e020a 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -206,7 +206,7 @@
 ) -> McfResult {
     let span = statement.source_info.span;
     match &statement.kind {
-        StatementKind::Assign(place, rval) => {
+        StatementKind::Assign(box(place, rval)) => {
             check_place(place, span)?;
             check_rvalue(tcx, body, rval, span)
         }
@@ -249,28 +249,26 @@
     place: &Place<'tcx>,
     span: Span,
 ) -> McfResult {
-    place.iterate(|place_base, place_projection| {
-        for proj in place_projection {
-            match proj.elem {
-                ProjectionElem::Downcast(..) => {
-                    return Err((span, "`match` or `if let` in `const fn` is unstable".into()));
-                }
-                ProjectionElem::ConstantIndex { .. }
-                | ProjectionElem::Subslice { .. }
-                | ProjectionElem::Deref
-                | ProjectionElem::Field(..)
-                | ProjectionElem::Index(_) => {}
+    for elem in place.projection.iter() {
+        match elem {
+            ProjectionElem::Downcast(..) => {
+                return Err((span, "`match` or `if let` in `const fn` is unstable".into()));
             }
+            ProjectionElem::ConstantIndex { .. }
+            | ProjectionElem::Subslice { .. }
+            | ProjectionElem::Deref
+            | ProjectionElem::Field(..)
+            | ProjectionElem::Index(_) => {}
         }
+    }
 
-        match place_base {
-            PlaceBase::Static(box Static { kind: StaticKind::Static, .. }) => {
-                Err((span, "cannot access `static` items in const fn".into()))
-            }
-            PlaceBase::Local(_)
-            | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => Ok(()),
+    match place.base {
+        PlaceBase::Static(box Static { kind: StaticKind::Static, .. }) => {
+            Err((span, "cannot access `static` items in const fn".into()))
         }
-    })
+        PlaceBase::Local(_)
+        | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => Ok(()),
+    }
 }
 
 fn check_terminator(
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index 73089a2..70b1194 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -41,10 +41,10 @@
                     // These are all nops in a landing pad
                 }
 
-                StatementKind::Assign(Place {
+                StatementKind::Assign(box(Place {
                     base: PlaceBase::Local(_),
-                    projection: None,
-                }, box Rvalue::Use(_)) => {
+                    projection: box [],
+                }, Rvalue::Use(_))) => {
                     // Writing to a local (e.g., a drop flag) does not
                     // turn a landing pad to a non-nop
                 }
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 1d3bf24..68fa082 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -120,11 +120,11 @@
     let peek_arg_place = match args[0] {
         mir::Operand::Copy(ref place @ mir::Place {
             base: mir::PlaceBase::Local(_),
-            projection: None,
+            projection: box [],
         }) |
         mir::Operand::Move(ref place @ mir::Place {
             base: mir::PlaceBase::Local(_),
-            projection: None,
+            projection: box [],
         }) => Some(place),
         _ => None,
     };
@@ -150,7 +150,7 @@
     for (j, stmt) in statements.iter().enumerate() {
         debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt);
         let (place, rvalue) = match stmt.kind {
-            mir::StatementKind::Assign(ref place, ref rvalue) => {
+            mir::StatementKind::Assign(box(ref place, ref rvalue)) => {
                 (place, rvalue)
             }
             mir::StatementKind::FakeRead(..) |
@@ -166,7 +166,7 @@
         };
 
         if place == peek_arg_place {
-            if let mir::Rvalue::Ref(_, mir::BorrowKind::Shared, ref peeking_at_place) = **rvalue {
+            if let mir::Rvalue::Ref(_, mir::BorrowKind::Shared, ref peeking_at_place) = *rvalue {
                 // Okay, our search is over.
                 match move_data.rev_lookup.find(peeking_at_place.as_ref()) {
                     LookupResult::Exact(peek_mpi) => {
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
index 8199a25..34ad5cb 100644
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ b/src/librustc_mir/transform/uniform_array_move_out.rs
@@ -61,14 +61,14 @@
                     rvalue: &Rvalue<'tcx>,
                     location: Location) {
         if let Rvalue::Use(Operand::Move(ref src_place)) = rvalue {
-            if let Some(ref proj) = src_place.projection {
+            if let box [proj_base @ .., elem] = &src_place.projection {
                 if let ProjectionElem::ConstantIndex{offset: _,
                                                      min_length: _,
-                                                     from_end: false} = proj.elem {
+                                                     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;
+                        Place::ty_from(&src_place.base, proj_base, self.body, self.tcx).ty;
                     if let ty::Array(item_ty, const_size) = place_ty.sty {
                         if let Some(size) = const_size.try_eval_usize(self.tcx, self.param_env) {
                             assert!(size <= u32::max_value() as u64,
@@ -78,7 +78,7 @@
                                 location,
                                 dst_place,
                                 &src_place.base,
-                                proj,
+                                &src_place.projection,
                                 item_ty,
                                 size as u32,
                             );
@@ -97,73 +97,76 @@
                location: Location,
                dst_place: &Place<'tcx>,
                base: &PlaceBase<'tcx>,
-               proj: &Projection<'tcx>,
+               proj: &[PlaceElem<'tcx>],
                item_ty: &'tcx ty::TyS<'tcx>,
                size: u32) {
-        match proj.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));
+        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: projection.into_boxed_slice(),
+                                                      }
+                                                  )
+                                              )
+                        );
+                        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,
-                                          Place::from(temp),
+                                          dst_place.clone(),
                                           Rvalue::Use(
                                               Operand::Move(
                                                   Place {
                                                       base: base.clone(),
-                                                      projection: Some(box Projection {
-                                                          base: proj.base.clone(),
-                                                          elem: ProjectionElem::ConstantIndex {
-                                                              offset: i,
-                                                              min_length: size,
-                                                              from_end: false,
-                                                          }
-                                                      }),
+                                                      projection: projection.into_boxed_slice(),
                                                   }
                                               )
                                           )
                     );
-                    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);
-                self.patch.add_assign(location,
-                                      dst_place.clone(),
-                                      Rvalue::Use(
-                                          Operand::Move(
-                                              Place {
-                                                  base: base.clone(),
-                                                  projection: Some(box Projection {
-                                                      base: proj.base.clone(),
-                                                      elem: ProjectionElem::ConstantIndex {
-                                                          offset: size - offset,
-                                                          min_length: size,
-                                                          from_end: false,
-                                                      },
-                                                  }),
-                                              }
-                                          )
-                                      )
-                );
-            }
-            _ => {}
         }
     }
 }
@@ -197,12 +200,12 @@
 
             for candidate in &visitor.candidates {
                 let statement = &body[candidate.block].statements[candidate.statement_index];
-                if let StatementKind::Assign(ref dst_place, ref rval) = statement.kind {
-                    if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = **rval {
+                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 {
                                 base: PlaceBase::Local(local),
-                                projection: None,
+                                projection: box [],
                             }) = item {
                                 let local_use = &visitor.locals_use[*local];
                                 let opt_index_and_place =
@@ -269,16 +272,17 @@
             }
             patch.make_nop(candidate);
             let size = opt_size.unwrap() as u32;
-            patch.add_assign(candidate,
-                             dst_place.clone(),
-                             Rvalue::Use(
-                                 Operand::Move(
-                                     Place {
-                                         base: src_place.base.clone(),
-                                         projection: Some(box Projection {
-                                             base: src_place.projection.clone(),
-                                             elem: ProjectionElem::Subslice{
-                                                 from: min, to: size - max - 1}})})));
+
+            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: projection.into_boxed_slice(),
+                })),
+            );
         }
     }
 
@@ -289,23 +293,34 @@
             if block.statements.len() > location.statement_index {
                 let statement = &block.statements[location.statement_index];
                 if let StatementKind::Assign(
-                    Place {
-                        base: PlaceBase::Local(_),
-                        projection: None,
-                    },
-                    box Rvalue::Use(Operand::Move(Place {
-                        base,
-                        projection: Some(box Projection {
-                            base: proj_base,
-                            elem: ProjectionElem::ConstantIndex {
+                    box(
+                        Place {
+                            base: PlaceBase::Local(_),
+                            projection: box [],
+                        },
+                        Rvalue::Use(Operand::Move(Place {
+                            base: _,
+                            projection: box [.., ProjectionElem::ConstantIndex {
                                 offset, min_length: _, from_end: false
-                            }
-                        }),
-                    }))) = &statement.kind {
-                    return Some((*offset, PlaceRef {
-                        base,
-                        projection: proj_base,
-                    }))
+                            }],
+                        })),
+                    )
+                ) = &statement.kind {
+                    // FIXME remove once we can use slices patterns
+                    if let StatementKind::Assign(
+                        box(
+                            _,
+                            Rvalue::Use(Operand::Move(Place {
+                                base,
+                                projection: box [proj_base @ .., _],
+                            })),
+                        )
+                    ) = &statement.kind {
+                        return Some((*offset, PlaceRef {
+                            base,
+                            projection: proj_base,
+                        }))
+                    }
                 }
             }
         }
diff --git a/src/librustc_mir/util/aggregate.rs b/src/librustc_mir/util/aggregate.rs
index 98e7067..b3565d4 100644
--- a/src/librustc_mir/util/aggregate.rs
+++ b/src/librustc_mir/util/aggregate.rs
@@ -24,7 +24,7 @@
             if adt_def.is_enum() {
                 set_discriminant = Some(Statement {
                     kind: StatementKind::SetDiscriminant {
-                        place: lhs.clone(),
+                        place: box(lhs.clone()),
                         variant_index,
                     },
                     source_info,
@@ -39,7 +39,7 @@
             let variant_index = VariantIdx::new(0);
             set_discriminant = Some(Statement {
                 kind: StatementKind::SetDiscriminant {
-                    place: lhs.clone(),
+                    place: box(lhs.clone()),
                     variant_index,
                 },
                 source_info,
@@ -70,7 +70,7 @@
         };
         Statement {
             source_info,
-            kind: StatementKind::Assign(lhs_field, box Rvalue::Use(op)),
+            kind: StatementKind::Assign(box(lhs_field, Rvalue::Use(op))),
         }
     }).chain(set_discriminant)
 }
diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs
index b8ef77d..a75c1af 100644
--- a/src/librustc_mir/util/alignment.rs
+++ b/src/librustc_mir/util/alignment.rs
@@ -38,14 +38,15 @@
 where
     L: HasLocalDecls<'tcx>,
 {
-    let mut place_projection = &place.projection;
+    let mut cursor = &*place.projection;
+    while let [proj_base @ .., elem] = cursor {
+        cursor = proj_base;
 
-    while let Some(proj) = place_projection {
-        match proj.elem {
+        match elem {
             // encountered a Deref, which is ABI-aligned
             ProjectionElem::Deref => break,
             ProjectionElem::Field(..) => {
-                let ty = Place::ty_from(&place.base, &proj.base, local_decls, tcx).ty;
+                let ty = Place::ty_from(&place.base, proj_base, local_decls, tcx).ty;
                 match ty.sty {
                     ty::Adt(def, _) if def.repr.packed() => {
                         return true
@@ -55,7 +56,6 @@
             }
             _ => {}
         }
-        place_projection = &proj.base;
     }
 
     false
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index 3359d1b..cf9ef55 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -50,7 +50,7 @@
             self,
             span,
             E0381,
-            "{} of possibly uninitialized variable: `{}`",
+            "{} of possibly-uninitialized variable: `{}`",
             verb,
             desc,
         )
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index f3e03e7..52ad97b 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -586,10 +586,7 @@
                 BorrowKind::Mut { allow_two_phase_borrow: false },
                 Place {
                     base: PlaceBase::Local(cur),
-                    projection: Some(Box::new(Projection {
-                        base: None,
-                        elem: ProjectionElem::Deref,
-                    })),
+                    projection: Box::new([ProjectionElem::Deref]),
                 }
              ),
              Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one))
@@ -981,7 +978,7 @@
     fn assign(&self, lhs: &Place<'tcx>, rhs: Rvalue<'tcx>) -> Statement<'tcx> {
         Statement {
             source_info: self.source_info,
-            kind: StatementKind::Assign(lhs.clone(), box rhs)
+            kind: StatementKind::Assign(box(lhs.clone(), rhs))
         }
     }
 }
diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs
index eb457da..2ea9924 100644
--- a/src/librustc_mir/util/patch.rs
+++ b/src/librustc_mir/util/patch.rs
@@ -120,7 +120,7 @@
     }
 
     pub fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) {
-        self.add_statement(loc, StatementKind::Assign(place, box rv));
+        self.add_statement(loc, StatementKind::Assign(box(place, rv)));
     }
 
     pub fn make_nop(&mut self, loc: Location) {
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index ac27019..c35c9e4 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -227,12 +227,12 @@
     pass_name: &str,
     disambiguator: &dyn Display,
     source: MirSource<'tcx>,
-) -> io::Result<fs::File> {
+) -> io::Result<io::BufWriter<fs::File>> {
     let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, source);
     if let Some(parent) = file_path.parent() {
         fs::create_dir_all(parent)?;
     }
-    fs::File::create(&file_path)
+    Ok(io::BufWriter::new(fs::File::create(&file_path)?))
 }
 
 /// Write out a human-readable textual representation for the given MIR.
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
index 1c66b0a..a81786e 100644
--- a/src/librustc_msan/build.rs
+++ b/src/librustc_msan/build.rs
@@ -4,6 +4,10 @@
 use cmake::Config;
 
 fn main() {
+    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
+    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
+        return;
+    }
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
         build_helper::restore_library_path();
 
diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs
index a30cd8a..af07c79 100644
--- a/src/librustc_passes/error_codes.rs
+++ b/src/librustc_passes/error_codes.rs
@@ -1,6 +1,4 @@
-use syntax::{register_diagnostics, register_long_diagnostics};
-
-register_long_diagnostics! {
+syntax::register_diagnostics! {
 /*
 E0014: r##"
 Constants can only be initialized by a constant value or, in a future
@@ -320,10 +318,8 @@
 ```
 
 Switch to the Rust 2018 edition to use `async fn`.
-"##
-}
-
-register_diagnostics! {
+"##,
+;
     E0226, // only a single explicit lifetime bound is permitted
     E0472, // asm! is unsupported on this target
     E0561, // patterns aren't allowed in function pointer types
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 5614b57..a5a8315 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -8,8 +8,7 @@
 
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(bind_by_move_pattern_guards)]
-#![feature(rustc_diagnostic_macros)]
+#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))]
 
 #![recursion_limit="256"]
 
@@ -18,7 +17,7 @@
 
 use rustc::ty::query::Providers;
 
-mod error_codes;
+pub mod error_codes;
 
 pub mod ast_validation;
 pub mod rvalue_promotion;
@@ -26,8 +25,6 @@
 pub mod layout_test;
 pub mod loops;
 
-__build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
-
 pub fn provide(providers: &mut Providers<'_>) {
     rvalue_promotion::provide(providers);
     loops::provide(providers);
diff --git a/src/librustc_plugin/error_codes.rs b/src/librustc_plugin/error_codes.rs
index b5f6a8d..7b3f01c 100644
--- a/src/librustc_plugin/error_codes.rs
+++ b/src/librustc_plugin/error_codes.rs
@@ -1,9 +1,4 @@
-use syntax::{register_diagnostics, register_long_diagnostics};
-
-register_long_diagnostics! {
-
-}
-
-register_diagnostics! {
-    E0498  // malformed plugin attribute
+syntax::register_diagnostics! {
+;
+    E0498,  // malformed plugin attribute
 }
diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs
index 952bc9f..4e1a47c 100644
--- a/src/librustc_plugin/lib.rs
+++ b/src/librustc_plugin/lib.rs
@@ -54,15 +54,12 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(nll)]
-#![feature(rustc_diagnostic_macros)]
 
 #![recursion_limit="256"]
 
 pub use registry::Registry;
 
-mod error_codes;
+pub mod error_codes;
 pub mod registry;
 pub mod load;
 pub mod build;
-
-__build_diagnostic_array! { librustc_plugin, DIAGNOSTICS }
diff --git a/src/librustc_privacy/error_codes.rs b/src/librustc_privacy/error_codes.rs
index 70a799d..6706646 100644
--- a/src/librustc_privacy/error_codes.rs
+++ b/src/librustc_privacy/error_codes.rs
@@ -1,4 +1,4 @@
-register_long_diagnostics! {
+syntax::register_diagnostics! {
 
 E0445: r##"
 A private trait was used on a public type parameter bound. Erroneous code
@@ -154,8 +154,5 @@
 ```
 "##,
 
-}
-
-register_diagnostics! {
 //  E0450, moved into resolve
 }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 1460589..1e61f78 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -2,7 +2,6 @@
 
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(rustc_diagnostic_macros)]
 
 #![recursion_limit="256"]
 
@@ -31,7 +30,7 @@
 use std::{cmp, fmt, mem};
 use std::marker::PhantomData;
 
-mod error_codes;
+pub mod error_codes;
 
 ////////////////////////////////////////////////////////////////////////////////
 /// Generic infrastructure used to implement specific visitors below.
@@ -2035,5 +2034,3 @@
     };
     krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
 }
-
-__build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 165a4c7..11dcf5b 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -31,7 +31,7 @@
 use syntax::attr;
 
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
-use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
+use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax::ext::expand::AstFragment;
 use syntax::ext::hygiene::ExpnId;
@@ -126,7 +126,8 @@
     crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
         let def_id = match self.macro_defs.get(&expn_id) {
             Some(def_id) => *def_id,
-            None => return self.graph_root,
+            None => return self.ast_transform_scopes.get(&expn_id)
+                .unwrap_or(&self.graph_root),
         };
         if let Some(id) = self.definitions.as_local_node_id(def_id) {
             self.local_macro_def_scopes[&id]
@@ -579,7 +580,7 @@
     }
 
     /// Constructs the reduced graph for one item.
-    fn build_reduced_graph_for_item(&mut self, item: &Item) {
+    fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
         let parent_scope = &self.parent_scope;
         let parent = parent_scope.module;
         let expansion = parent_scope.expansion;
@@ -715,22 +716,17 @@
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
             }
 
-            ItemKind::Enum(ref enum_definition, _) => {
-                let module_kind = ModuleKind::Def(
-                    DefKind::Enum,
-                    self.r.definitions.local_def_id(item.id),
-                    ident.name,
-                );
+            ItemKind::Enum(_, _) => {
+                let def_id = self.r.definitions.local_def_id(item.id);
+                self.r.variant_vis.insert(def_id, vis);
+                let module_kind = ModuleKind::Def(DefKind::Enum, def_id, ident.name);
                 let module = self.r.new_module(parent,
                                              module_kind,
                                              parent.normal_ancestor_id,
                                              expansion,
                                              item.span);
                 self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
-
-                for variant in &(*enum_definition).variants {
-                    self.build_reduced_graph_for_variant(variant, module, vis);
-                }
+                self.parent_scope.module = module;
             }
 
             ItemKind::TraitAlias(..) => {
@@ -815,40 +811,6 @@
         }
     }
 
-    // Constructs the reduced graph for one variant. Variants exist in the
-    // type and value namespaces.
-    fn build_reduced_graph_for_variant(&mut self,
-                                       variant: &Variant,
-                                       parent: Module<'a>,
-                                       vis: ty::Visibility) {
-        let expn_id = self.parent_scope.expansion;
-        let ident = variant.ident;
-
-        // Define a name in the type namespace.
-        let def_id = self.r.definitions.local_def_id(variant.id);
-        let res = Res::Def(DefKind::Variant, def_id);
-        self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id));
-
-        // If the variant is marked as non_exhaustive then lower the visibility to within the
-        // crate.
-        let mut ctor_vis = vis;
-        let has_non_exhaustive = attr::contains_name(&variant.attrs, sym::non_exhaustive);
-        if has_non_exhaustive && vis == ty::Visibility::Public {
-            ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
-        }
-
-        // Define a constructor name in the value namespace.
-        // Braced variants, unlike structs, generate unusable names in
-        // value namespace, they are reserved for possible future use.
-        // It's ok to use the variant's id as a ctor id since an
-        // error will be reported on any use of such resolution anyway.
-        let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id);
-        let ctor_def_id = self.r.definitions.local_def_id(ctor_node_id);
-        let ctor_kind = CtorKind::from_ast(&variant.data);
-        let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
-        self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
-    }
-
     /// Constructs the reduced graph for one foreign item.
     fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
         let (res, ns) = match item.node {
@@ -1188,7 +1150,6 @@
             ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
             _ => false,
         };
-
         let orig_current_module = self.parent_scope.module;
         let orig_current_legacy_scope = self.parent_scope.legacy;
         self.build_reduced_graph_for_item(item);
@@ -1252,9 +1213,7 @@
         let expansion = self.parent_scope.expansion;
         self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion));
 
-        self.parent_scope.module = parent.parent.unwrap(); // nearest normal ancestor
         visit::walk_trait_item(self, item);
-        self.parent_scope.module = parent;
     }
 
     fn visit_token(&mut self, t: Token) {
@@ -1273,4 +1232,92 @@
         }
         visit::walk_attribute(self, attr);
     }
+
+    fn visit_arm(&mut self, arm: &'b ast::Arm) {
+        if arm.is_placeholder {
+            self.visit_invoc(arm.id);
+        } else {
+            visit::walk_arm(self, arm);
+        }
+    }
+
+    fn visit_field(&mut self, f: &'b ast::Field) {
+        if f.is_placeholder {
+            self.visit_invoc(f.id);
+        } else {
+            visit::walk_field(self, f);
+        }
+    }
+
+    fn visit_field_pattern(&mut self, fp: &'b ast::FieldPat) {
+        if fp.is_placeholder {
+            self.visit_invoc(fp.id);
+        } else {
+            visit::walk_field_pattern(self, fp);
+        }
+    }
+
+    fn visit_generic_param(&mut self, param: &'b ast::GenericParam) {
+        if param.is_placeholder {
+            self.visit_invoc(param.id);
+        } else {
+            visit::walk_generic_param(self, param);
+        }
+    }
+
+    fn visit_param(&mut self, p: &'b ast::Param) {
+        if p.is_placeholder {
+            self.visit_invoc(p.id);
+        } else {
+            visit::walk_param(self, p);
+        }
+    }
+
+    fn visit_struct_field(&mut self, sf: &'b ast::StructField) {
+        if sf.is_placeholder {
+            self.visit_invoc(sf.id);
+        } else {
+            visit::walk_struct_field(self, sf);
+        }
+    }
+
+    // Constructs the reduced graph for one variant. Variants exist in the
+    // type and value namespaces.
+    fn visit_variant(&mut self, variant: &'b ast::Variant) {
+        if variant.is_placeholder {
+            self.visit_invoc(variant.id);
+            return;
+        }
+
+        let parent = self.parent_scope.module;
+        let vis = self.r.variant_vis[&parent.def_id().expect("enum without def-id")];
+        let expn_id = self.parent_scope.expansion;
+        let ident = variant.ident;
+
+        // Define a name in the type namespace.
+        let def_id = self.r.definitions.local_def_id(variant.id);
+        let res = Res::Def(DefKind::Variant, def_id);
+        self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id));
+
+        // If the variant is marked as non_exhaustive then lower the visibility to within the
+        // crate.
+        let mut ctor_vis = vis;
+        let has_non_exhaustive = attr::contains_name(&variant.attrs, sym::non_exhaustive);
+        if has_non_exhaustive && vis == ty::Visibility::Public {
+            ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
+        }
+
+        // Define a constructor name in the value namespace.
+        // Braced variants, unlike structs, generate unusable names in
+        // value namespace, they are reserved for possible future use.
+        // It's ok to use the variant's id as a ctor id since an
+        // error will be reported on any use of such resolution anyway.
+        let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id);
+        let ctor_def_id = self.r.definitions.local_def_id(ctor_node_id);
+        let ctor_kind = CtorKind::from_ast(&variant.data);
+        let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
+        self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
+
+        visit::walk_variant(self, variant);
+    }
 }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index b79e0c2..c479912 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -604,6 +604,14 @@
         if lookup_ident.span.rust_2018() {
             let extern_prelude_names = self.extern_prelude.clone();
             for (ident, _) in extern_prelude_names.into_iter() {
+                if ident.span.from_expansion() {
+                    // Idents are adjusted to the root context before being
+                    // resolved in the extern prelude, so reporting this to the
+                    // user is no help. This skips the injected
+                    // `extern crate std` in the 2018 edition, which would
+                    // otherwise cause duplicate suggestions.
+                    continue;
+                }
                 if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
                                                                                     ident.span) {
                     let crate_root = self.get_module(DefId {
diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs
index 1faaf97..adbff67 100644
--- a/src/librustc_resolve/error_codes.rs
+++ b/src/librustc_resolve/error_codes.rs
@@ -1,9 +1,7 @@
-use syntax::{register_diagnostics, register_long_diagnostics};
-
 // Error messages for EXXXX errors.  Each message should start and end with a
 // new line, and be wrapped to 80 characters.  In vim you can `:set tw=80` and
 // use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
-register_long_diagnostics! {
+syntax::register_diagnostics! {
 
 E0128: r##"
 Type parameter defaults can only use parameters that occur before them.
@@ -1662,10 +1660,7 @@
 }
 ```
 "##,
-
-}
-
-register_diagnostics! {
+;
 //  E0153, unused error code
 //  E0157, unused error code
 //  E0257,
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index e15d02a..aae283b 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -9,7 +9,7 @@
 use RibKind::*;
 
 use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
-use crate::{Module, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult};
+use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
 use log::debug;
@@ -18,7 +18,7 @@
 use rustc::hir::def::Namespace::{self, *};
 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc::hir::TraitCandidate;
-use rustc::util::nodemap::FxHashMap;
+use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use smallvec::{smallvec, SmallVec};
 use syntax::{unwrap_or, walk_list};
 use syntax::ast::*;
@@ -35,8 +35,10 @@
 
 type Res = def::Res<NodeId>;
 
+type IdentMap<T> = FxHashMap<Ident, T>;
+
 /// Map from the name in a pattern to its binding mode.
-type BindingMap = FxHashMap<Ident, BindingInfo>;
+type BindingMap = IdentMap<BindingInfo>;
 
 #[derive(Copy, Clone, Debug)]
 struct BindingInfo {
@@ -73,6 +75,16 @@
     }
 }
 
+/// Denotes whether the context for the set of already bound bindings is a `Product`
+/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
+/// See those functions for more information.
+enum PatBoundCtx {
+    /// A product pattern context, e.g., `Variant(a, b)`.
+    Product,
+    /// An or-pattern context, e.g., `p_0 | ... | p_n`.
+    Or,
+}
+
 /// The rib kind restricts certain accesses,
 /// e.g. to a `Res::Local` of an outer item.
 #[derive(Copy, Clone, Debug)]
@@ -143,7 +155,7 @@
 /// resolving, the name is looked up from inside out.
 #[derive(Debug)]
 crate struct Rib<'a, R = Res> {
-    pub bindings: FxHashMap<Ident, R>,
+    pub bindings: IdentMap<R>,
     pub kind: RibKind<'a>,
 }
 
@@ -286,18 +298,18 @@
     }
 
     fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
-        __diagnostic_used!(E0404);
-        __diagnostic_used!(E0405);
-        __diagnostic_used!(E0412);
-        __diagnostic_used!(E0422);
-        __diagnostic_used!(E0423);
-        __diagnostic_used!(E0425);
-        __diagnostic_used!(E0531);
-        __diagnostic_used!(E0532);
-        __diagnostic_used!(E0573);
-        __diagnostic_used!(E0574);
-        __diagnostic_used!(E0575);
-        __diagnostic_used!(E0576);
+        syntax::diagnostic_used!(E0404);
+        syntax::diagnostic_used!(E0405);
+        syntax::diagnostic_used!(E0412);
+        syntax::diagnostic_used!(E0422);
+        syntax::diagnostic_used!(E0423);
+        syntax::diagnostic_used!(E0425);
+        syntax::diagnostic_used!(E0531);
+        syntax::diagnostic_used!(E0532);
+        syntax::diagnostic_used!(E0573);
+        syntax::diagnostic_used!(E0574);
+        syntax::diagnostic_used!(E0575);
+        syntax::diagnostic_used!(E0576);
         match (self, has_unexpected_resolution) {
             (PathSource::Trait(_), true) => "E0404",
             (PathSource::Trait(_), false) => "E0405",
@@ -406,50 +418,32 @@
             visit::walk_foreign_item(this, foreign_item);
         });
     }
-    fn visit_fn(&mut self,
-                function_kind: FnKind<'tcx>,
-                declaration: &'tcx FnDecl,
-                _: Span,
-                _: NodeId)
-    {
+    fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) {
         debug!("(resolving function) entering function");
-        let rib_kind = match function_kind {
+        let rib_kind = match fn_kind {
             FnKind::ItemFn(..) => FnItemRibKind,
             FnKind::Method(..) | FnKind::Closure(_) => NormalRibKind,
         };
 
         // Create a value rib for the function.
-        self.ribs[ValueNS].push(Rib::new(rib_kind));
+        self.with_rib(ValueNS, rib_kind, |this| {
+            // Create a label rib for the function.
+            this.with_label_rib(rib_kind, |this| {
+                // Add each argument to the rib.
+                this.resolve_params(&declaration.inputs);
 
-        // Create a label rib for the function.
-        self.label_ribs.push(Rib::new(rib_kind));
+                visit::walk_fn_ret_ty(this, &declaration.output);
 
-        // Add each argument to the rib.
-        let mut bindings_list = FxHashMap::default();
-        for argument in &declaration.inputs {
-            self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
+                // Resolve the function body, potentially inside the body of an async closure
+                match fn_kind {
+                    FnKind::ItemFn(.., body) |
+                    FnKind::Method(.., body) => this.visit_block(body),
+                    FnKind::Closure(body) => this.visit_expr(body),
+                };
 
-            self.visit_ty(&argument.ty);
-
-            debug!("(resolving function) recorded argument");
-        }
-        visit::walk_fn_ret_ty(self, &declaration.output);
-
-        // Resolve the function body, potentially inside the body of an async closure
-        match function_kind {
-            FnKind::ItemFn(.., body) |
-            FnKind::Method(.., body) => {
-                self.visit_block(body);
-            }
-            FnKind::Closure(body) => {
-                self.visit_expr(body);
-            }
-        };
-
-        debug!("(resolving function) leaving function");
-
-        self.label_ribs.pop();
-        self.ribs[ValueNS].pop();
+                debug!("(resolving function) leaving function");
+            })
+        });
     }
 
     fn visit_generics(&mut self, generics: &'tcx Generics) {
@@ -528,13 +522,14 @@
         // although it may be useful to track other components as well for diagnostics.
         let graph_root = resolver.graph_root;
         let parent_scope = ParentScope::module(graph_root);
+        let start_rib_kind = ModuleRibKind(graph_root);
         LateResolutionVisitor {
             r: resolver,
             parent_scope,
             ribs: PerNS {
-                value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
-                type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
-                macro_ns: vec![Rib::new(ModuleRibKind(graph_root))],
+                value_ns: vec![Rib::new(start_rib_kind)],
+                type_ns: vec![Rib::new(start_rib_kind)],
+                macro_ns: vec![Rib::new(start_rib_kind)],
             },
             label_ribs: Vec::new(),
             current_trait_ref: None,
@@ -588,23 +583,32 @@
     // generate a fake "implementation scope" containing all the
     // implementations thus found, for compatibility with old resolve pass.
 
-    fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T
-    {
+    /// Do some `work` within a new innermost rib of the given `kind` in the given namespace (`ns`).
+    fn with_rib<T>(
+        &mut self,
+        ns: Namespace,
+        kind: RibKind<'a>,
+        work: impl FnOnce(&mut Self) -> T,
+    ) -> T {
+        self.ribs[ns].push(Rib::new(kind));
+        let ret = work(self);
+        self.ribs[ns].pop();
+        ret
+    }
+
+    fn with_scope<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
         let id = self.r.definitions.local_def_id(id);
         let module = self.r.module_map.get(&id).cloned(); // clones a reference
         if let Some(module) = module {
             // Move down in the graph.
             let orig_module = replace(&mut self.parent_scope.module, module);
-            self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
-            self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
-
-            let ret = f(self);
-
-            self.parent_scope.module = orig_module;
-            self.ribs[ValueNS].pop();
-            self.ribs[TypeNS].pop();
-            ret
+            self.with_rib(ValueNS, ModuleRibKind(module), |this| {
+                this.with_rib(TypeNS, ModuleRibKind(module), |this| {
+                    let ret = f(this);
+                    this.parent_scope.module = orig_module;
+                    ret
+                })
+            })
         } else {
             f(self)
         }
@@ -808,7 +812,7 @@
     }
 
     fn with_generic_param_rib<'c, F>(&'c mut self, generic_params: GenericParameters<'a, 'c>, f: F)
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
+        where F: FnOnce(&mut Self)
     {
         debug!("with_generic_param_rib");
         match generic_params {
@@ -894,38 +898,24 @@
         }
     }
 
-    fn with_label_rib<F>(&mut self, f: F)
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
-    {
-        self.label_ribs.push(Rib::new(NormalRibKind));
+    fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) {
+        self.label_ribs.push(Rib::new(kind));
         f(self);
         self.label_ribs.pop();
     }
 
-    fn with_item_rib<F>(&mut self, f: F)
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
-    {
-        self.ribs[ValueNS].push(Rib::new(ItemRibKind));
-        self.ribs[TypeNS].push(Rib::new(ItemRibKind));
-        f(self);
-        self.ribs[TypeNS].pop();
-        self.ribs[ValueNS].pop();
+    fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
+        self.with_rib(ValueNS, ItemRibKind, |this| this.with_rib(TypeNS, ItemRibKind, f))
     }
 
-    fn with_constant_rib<F>(&mut self, f: F)
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
-    {
+    fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) {
         debug!("with_constant_rib");
-        self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
-        self.label_ribs.push(Rib::new(ConstantItemRibKind));
-        f(self);
-        self.label_ribs.pop();
-        self.ribs[ValueNS].pop();
+        self.with_rib(ValueNS, ConstantItemRibKind, |this| {
+            this.with_label_rib(ConstantItemRibKind, f);
+        });
     }
 
-    fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T
-    {
+    fn with_current_self_type<T>(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T {
         // Handle nested impls (inside fn bodies)
         let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
         let result = f(self);
@@ -933,9 +923,7 @@
         result
     }
 
-    fn with_current_self_item<T, F>(&mut self, self_item: &Item, f: F) -> T
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T
-    {
+    fn with_current_self_item<T>(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T {
         let previous_value = replace(&mut self.current_self_item, Some(self_item.id));
         let result = f(self);
         self.current_self_item = previous_value;
@@ -943,9 +931,11 @@
     }
 
     /// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412.
-    fn with_trait_items<T, F>(&mut self, trait_items: &Vec<TraitItem>, f: F) -> T
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T
-    {
+    fn with_trait_items<T>(
+        &mut self,
+        trait_items: &Vec<TraitItem>,
+        f: impl FnOnce(&mut Self) -> T,
+    ) -> T {
         let trait_assoc_types = replace(
             &mut self.current_trait_assoc_types,
             trait_items.iter().filter_map(|item| match &item.node {
@@ -959,9 +949,11 @@
     }
 
     /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`).
-    fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>, Option<DefId>) -> T
-    {
+    fn with_optional_trait_ref<T>(
+        &mut self,
+        opt_trait_ref: Option<&TraitRef>,
+        f: impl FnOnce(&mut Self, Option<DefId>) -> T
+    ) -> T {
         let mut new_val = None;
         let mut new_id = None;
         if let Some(trait_ref) = opt_trait_ref {
@@ -996,27 +988,18 @@
         result
     }
 
-    fn with_self_rib<F>(&mut self, self_res: Res, f: F)
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
-    {
+    fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) {
         let mut self_type_rib = Rib::new(NormalRibKind);
 
         // Plain insert (no renaming, since types are not currently hygienic)
         self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
-        self.ribs[TypeNS].push(self_type_rib);
+        self.ribs[ns].push(self_type_rib);
         f(self);
-        self.ribs[TypeNS].pop();
+        self.ribs[ns].pop();
     }
 
-    fn with_self_struct_ctor_rib<F>(&mut self, impl_id: DefId, f: F)
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
-    {
-        let self_res = Res::SelfCtor(impl_id);
-        let mut self_type_rib = Rib::new(NormalRibKind);
-        self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
-        self.ribs[ValueNS].push(self_type_rib);
-        f(self);
-        self.ribs[ValueNS].pop();
+    fn with_self_rib(&mut self, self_res: Res, f: impl FnOnce(&mut Self)) {
+        self.with_self_rib_ns(TypeNS, self_res, f)
     }
 
     fn resolve_implementation(&mut self,
@@ -1044,8 +1027,8 @@
                         this.visit_generics(generics);
                         // Resolve the items within the impl.
                         this.with_current_self_type(self_type, |this| {
-                            this.with_self_struct_ctor_rib(item_def_id, |this| {
-                                debug!("resolve_implementation with_self_struct_ctor_rib");
+                            this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
+                                debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
                                 for impl_item in impl_items {
                                     // We also need a new scope for the impl item type parameters.
                                     let generic_params = HasGenericParams(&impl_item.generics,
@@ -1135,6 +1118,15 @@
         }
     }
 
+    fn resolve_params(&mut self, params: &[Param]) {
+        let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
+        for Param { pat, ty, .. } in params {
+            self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
+            self.visit_ty(ty);
+            debug!("(resolving function / closure) recorded parameter");
+        }
+    }
+
     fn resolve_local(&mut self, local: &Local) {
         // Resolve the type.
         walk_list!(self, visit_ty, &local.ty);
@@ -1143,72 +1135,93 @@
         walk_list!(self, visit_expr, &local.init);
 
         // Resolve the pattern.
-        self.resolve_pattern(&local.pat, PatternSource::Let, &mut FxHashMap::default());
+        self.resolve_pattern_top(&local.pat, PatternSource::Let);
     }
 
-    // build a map from pattern identifiers to binding-info's.
-    // this is done hygienically. This could arise for a macro
-    // that expands into an or-pattern where one 'x' was from the
-    // user and one 'x' came from the macro.
+    /// build a map from pattern identifiers to binding-info's.
+    /// this is done hygienically. This could arise for a macro
+    /// that expands into an or-pattern where one 'x' was from the
+    /// user and one 'x' came from the macro.
     fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
         let mut binding_map = FxHashMap::default();
 
         pat.walk(&mut |pat| {
-            if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node {
-                if sub_pat.is_some() || match self.r.partial_res_map.get(&pat.id)
-                                                                  .map(|res| res.base_res()) {
-                    Some(Res::Local(..)) => true,
-                    _ => false,
-                } {
-                    let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
-                    binding_map.insert(ident, binding_info);
+            match pat.node {
+                PatKind::Ident(binding_mode, ident, ref sub_pat)
+                    if sub_pat.is_some() || self.is_base_res_local(pat.id) =>
+                {
+                    binding_map.insert(ident, BindingInfo { span: ident.span, binding_mode });
                 }
+                PatKind::Or(ref ps) => {
+                    // Check the consistency of this or-pattern and
+                    // then add all bindings to the larger map.
+                    for bm in self.check_consistent_bindings(ps) {
+                        binding_map.extend(bm);
+                    }
+                    return false;
+                }
+                _ => {}
             }
+
             true
         });
 
         binding_map
     }
 
-    // Checks that all of the arms in an or-pattern have exactly the
-    // same set of bindings, with the same binding modes for each.
-    fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) {
+    fn is_base_res_local(&self, nid: NodeId) -> bool {
+        match self.r.partial_res_map.get(&nid).map(|res| res.base_res()) {
+            Some(Res::Local(..)) => true,
+            _ => false,
+        }
+    }
+
+    /// Checks that all of the arms in an or-pattern have exactly the
+    /// same set of bindings, with the same binding modes for each.
+    fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<BindingMap> {
         let mut missing_vars = FxHashMap::default();
         let mut inconsistent_vars = FxHashMap::default();
 
-        for pat_outer in pats.iter() {
-            let map_outer = self.binding_mode_map(&pat_outer);
+        // 1) Compute the binding maps of all arms.
+        let maps = pats.iter()
+            .map(|pat| self.binding_mode_map(pat))
+            .collect::<Vec<_>>();
 
-            for pat_inner in pats.iter().filter(|pat| pat.id != pat_outer.id) {
-                let map_inner = self.binding_mode_map(&pat_inner);
+        // 2) Record any missing bindings or binding mode inconsistencies.
+        for (map_outer, pat_outer) in pats.iter().enumerate().map(|(idx, pat)| (&maps[idx], pat)) {
+            // Check against all arms except for the same pattern which is always self-consistent.
+            let inners = pats.iter().enumerate()
+                .filter(|(_, pat)| pat.id != pat_outer.id)
+                .flat_map(|(idx, _)| maps[idx].iter())
+                .map(|(key, binding)| (key.name, map_outer.get(&key), binding));
 
-                for (&key_inner, &binding_inner) in map_inner.iter() {
-                    match map_outer.get(&key_inner) {
-                        None => {  // missing binding
-                            let binding_error = missing_vars
-                                .entry(key_inner.name)
-                                .or_insert(BindingError {
-                                    name: key_inner.name,
-                                    origin: BTreeSet::new(),
-                                    target: BTreeSet::new(),
-                                    could_be_path:
-                                        key_inner.name.as_str().starts_with(char::is_uppercase)
-                                });
-                            binding_error.origin.insert(binding_inner.span);
-                            binding_error.target.insert(pat_outer.span);
-                        }
-                        Some(binding_outer) => {  // check consistent binding
-                            if binding_outer.binding_mode != binding_inner.binding_mode {
-                                inconsistent_vars
-                                    .entry(key_inner.name)
-                                    .or_insert((binding_inner.span, binding_outer.span));
-                            }
+            for (name, info, &binding_inner) in inners {
+                match info {
+                    None => { // The inner binding is missing in the outer.
+                        let binding_error = missing_vars
+                            .entry(name)
+                            .or_insert_with(|| BindingError {
+                                name,
+                                origin: BTreeSet::new(),
+                                target: BTreeSet::new(),
+                                could_be_path: name.as_str().starts_with(char::is_uppercase),
+                            });
+                        binding_error.origin.insert(binding_inner.span);
+                        binding_error.target.insert(pat_outer.span);
+                    }
+                    Some(binding_outer) => {
+                        if binding_outer.binding_mode != binding_inner.binding_mode {
+                            // The binding modes in the outer and inner bindings differ.
+                            inconsistent_vars
+                                .entry(name)
+                                .or_insert((binding_inner.span, binding_outer.span));
                         }
                     }
                 }
             }
         }
 
+        // 3) Report all missing variables we found.
         let mut missing_vars = missing_vars.iter_mut().collect::<Vec<_>>();
         missing_vars.sort();
         for (name, mut v) in missing_vars {
@@ -1220,212 +1233,245 @@
                 ResolutionError::VariableNotBoundInPattern(v));
         }
 
+        // 4) Report all inconsistencies in binding modes we found.
         let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
         inconsistent_vars.sort();
         for (name, v) in inconsistent_vars {
             self.r.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
         }
+
+        // 5) Finally bubble up all the binding maps.
+        maps
+    }
+
+    /// Check the consistency of the outermost or-patterns.
+    fn check_consistent_bindings_top(&mut self, pat: &Pat) {
+        pat.walk(&mut |pat| match pat.node {
+            PatKind::Or(ref ps) => {
+                self.check_consistent_bindings(ps);
+                false
+            },
+            _ => true,
+        })
     }
 
     fn resolve_arm(&mut self, arm: &Arm) {
-        self.ribs[ValueNS].push(Rib::new(NormalRibKind));
-
-        self.resolve_pats(&arm.pats, PatternSource::Match);
-
-        if let Some(ref expr) = arm.guard {
-            self.visit_expr(expr)
-        }
-        self.visit_expr(&arm.body);
-
-        self.ribs[ValueNS].pop();
+        self.with_rib(ValueNS, NormalRibKind, |this| {
+            this.resolve_pattern_top(&arm.pat, PatternSource::Match);
+            walk_list!(this, visit_expr, &arm.guard);
+            this.visit_expr(&arm.body);
+        });
     }
 
-    /// Arising from `source`, resolve a sequence of patterns (top level or-patterns).
-    fn resolve_pats(&mut self, pats: &[P<Pat>], source: PatternSource) {
-        let mut bindings_list = FxHashMap::default();
-        for pat in pats {
-            self.resolve_pattern(pat, source, &mut bindings_list);
-        }
-        // This has to happen *after* we determine which pat_idents are variants
-        if pats.len() > 1 {
-            self.check_consistent_bindings(pats);
-        }
+    /// Arising from `source`, resolve a top level pattern.
+    fn resolve_pattern_top(&mut self, pat: &Pat, pat_src: PatternSource) {
+        let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
+        self.resolve_pattern(pat, pat_src, &mut bindings);
     }
 
-    fn resolve_block(&mut self, block: &Block) {
-        debug!("(resolving block) entering block");
-        // Move down in the graph, if there's an anonymous module rooted here.
-        let orig_module = self.parent_scope.module;
-        let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference
-
-        let mut num_macro_definition_ribs = 0;
-        if let Some(anonymous_module) = anonymous_module {
-            debug!("(resolving block) found anonymous module, moving down");
-            self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module)));
-            self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module)));
-            self.parent_scope.module = anonymous_module;
-        } else {
-            self.ribs[ValueNS].push(Rib::new(NormalRibKind));
-        }
-
-        // Descend into the block.
-        for stmt in &block.stmts {
-            if let StmtKind::Item(ref item) = stmt.node {
-                if let ItemKind::MacroDef(..) = item.node {
-                    num_macro_definition_ribs += 1;
-                    let res = self.r.definitions.local_def_id(item.id);
-                    self.ribs[ValueNS].push(Rib::new(MacroDefinition(res)));
-                    self.label_ribs.push(Rib::new(MacroDefinition(res)));
-                }
-            }
-
-            self.visit_stmt(stmt);
-        }
-
-        // Move back up.
-        self.parent_scope.module = orig_module;
-        for _ in 0 .. num_macro_definition_ribs {
-            self.ribs[ValueNS].pop();
-            self.label_ribs.pop();
-        }
-        self.ribs[ValueNS].pop();
-        if anonymous_module.is_some() {
-            self.ribs[TypeNS].pop();
-        }
-        debug!("(resolving block) leaving block");
+    fn resolve_pattern(
+        &mut self,
+        pat: &Pat,
+        pat_src: PatternSource,
+        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
+    ) {
+        self.resolve_pattern_inner(pat, pat_src, bindings);
+        // This has to happen *after* we determine which pat_idents are variants:
+        self.check_consistent_bindings_top(pat);
+        visit::walk_pat(self, pat);
     }
 
-    fn fresh_binding(&mut self,
-                     ident: Ident,
-                     pat_id: NodeId,
-                     outer_pat_id: NodeId,
-                     pat_src: PatternSource,
-                     bindings: &mut FxHashMap<Ident, NodeId>)
-                     -> Res {
-        // Add the binding to the local ribs, if it
-        // doesn't already exist in the bindings map. (We
-        // must not add it if it's in the bindings map
-        // because that breaks the assumptions later
-        // passes make about or-patterns.)
-        let ident = ident.modern_and_legacy();
-        let mut res = Res::Local(pat_id);
-        match bindings.get(&ident).cloned() {
-            Some(id) if id == outer_pat_id => {
-                // `Variant(a, a)`, error
-                self.r.report_error(
-                    ident.span,
-                    ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
-                        &ident.as_str())
-                );
-            }
-            Some(..) if pat_src == PatternSource::FnParam => {
-                // `fn f(a: u8, a: u8)`, error
-                self.r.report_error(
-                    ident.span,
-                    ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
-                        &ident.as_str())
-                );
-            }
-            Some(..) if pat_src == PatternSource::Match ||
-                        pat_src == PatternSource::Let => {
-                // `Variant1(a) | Variant2(a)`, ok
-                // Reuse definition from the first `a`.
-                res = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident];
-            }
-            Some(..) => {
-                span_bug!(ident.span, "two bindings with the same name from \
-                                       unexpected pattern source {:?}", pat_src);
-            }
-            None => {
-                // A completely fresh binding, add to the lists if it's valid.
-                if ident.name != kw::Invalid {
-                    bindings.insert(ident, outer_pat_id);
-                    self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, res);
-                }
-            }
-        }
-
-        res
-    }
-
-    fn resolve_pattern(&mut self,
-                       pat: &Pat,
-                       pat_src: PatternSource,
-                       // Maps idents to the node ID for the
-                       // outermost pattern that binds them.
-                       bindings: &mut FxHashMap<Ident, NodeId>) {
+    /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.
+    ///
+    /// ### `bindings`
+    ///
+    /// A stack of sets of bindings accumulated.
+    ///
+    /// In each set, `PatBoundCtx::Product` denotes that a found binding in it should
+    /// be interpreted as re-binding an already bound binding. This results in an error.
+    /// Meanwhile, `PatBound::Or` denotes that a found binding in the set should result
+    /// in reusing this binding rather than creating a fresh one.
+    ///
+    /// When called at the top level, the stack must have a single element
+    /// with `PatBound::Product`. Otherwise, pushing to the stack happens as
+    /// or-patterns (`p_0 | ... | p_n`) are encountered and the context needs
+    /// to be switched to `PatBoundCtx::Or` and then `PatBoundCtx::Product` for each `p_i`.
+    /// When each `p_i` has been dealt with, the top set is merged with its parent.
+    /// When a whole or-pattern has been dealt with, the thing happens.
+    ///
+    /// See the implementation and `fresh_binding` for more details.
+    fn resolve_pattern_inner(
+        &mut self,
+        pat: &Pat,
+        pat_src: PatternSource,
+        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
+    ) {
         // Visit all direct subpatterns of this pattern.
-        let outer_pat_id = pat.id;
         pat.walk(&mut |pat| {
             debug!("resolve_pattern pat={:?} node={:?}", pat, pat.node);
             match pat.node {
-                PatKind::Ident(bmode, ident, ref opt_pat) => {
-                    // First try to resolve the identifier as some existing
-                    // entity, then fall back to a fresh binding.
-                    let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS,
-                                                                      None, pat.span)
-                                      .and_then(LexicalScopeBinding::item);
-                    let res = binding.map(NameBinding::res).and_then(|res| {
-                        let is_syntactic_ambiguity = opt_pat.is_none() &&
-                            bmode == BindingMode::ByValue(Mutability::Immutable);
-                        match res {
-                            Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
-                            Res::Def(DefKind::Const, _) if is_syntactic_ambiguity => {
-                                // Disambiguate in favor of a unit struct/variant
-                                // or constant pattern.
-                                self.r.record_use(ident, ValueNS, binding.unwrap(), false);
-                                Some(res)
-                            }
-                            Res::Def(DefKind::Ctor(..), _)
-                            | Res::Def(DefKind::Const, _)
-                            | Res::Def(DefKind::Static, _) => {
-                                // This is unambiguously a fresh binding, either syntactically
-                                // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
-                                // to something unusable as a pattern (e.g., constructor function),
-                                // but we still conservatively report an error, see
-                                // issues/33118#issuecomment-233962221 for one reason why.
-                                self.r.report_error(
-                                    ident.span,
-                                    ResolutionError::BindingShadowsSomethingUnacceptable(
-                                        pat_src.descr(), ident.name, binding.unwrap())
-                                );
-                                None
-                            }
-                            Res::Def(DefKind::Fn, _) | Res::Err => {
-                                // These entities are explicitly allowed
-                                // to be shadowed by fresh bindings.
-                                None
-                            }
-                            res => {
-                                span_bug!(ident.span, "unexpected resolution for an \
-                                                       identifier in pattern: {:?}", res);
-                            }
-                        }
-                    }).unwrap_or_else(|| {
-                        self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
-                    });
-
+                PatKind::Ident(bmode, ident, ref sub) => {
+                    // First try to resolve the identifier as some existing entity,
+                    // then fall back to a fresh binding.
+                    let has_sub = sub.is_some();
+                    let res = self.try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
+                        .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
                     self.r.record_partial_res(pat.id, PartialRes::new(res));
                 }
-
                 PatKind::TupleStruct(ref path, ..) => {
                     self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct);
                 }
-
                 PatKind::Path(ref qself, ref path) => {
                     self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
                 }
-
                 PatKind::Struct(ref path, ..) => {
                     self.smart_resolve_path(pat.id, None, path, PathSource::Struct);
                 }
+                PatKind::Or(ref ps) => {
+                    // Add a new set of bindings to the stack. `Or` here records that when a
+                    // binding already exists in this set, it should not result in an error because
+                    // `V1(a) | V2(a)` must be allowed and are checked for consistency later.
+                    bindings.push((PatBoundCtx::Or, Default::default()));
+                    for p in ps {
+                        // Now we need to switch back to a product context so that each
+                        // part of the or-pattern internally rejects already bound names.
+                        // For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad.
+                        bindings.push((PatBoundCtx::Product, Default::default()));
+                        self.resolve_pattern_inner(p, pat_src, bindings);
+                        // Move up the non-overlapping bindings to the or-pattern.
+                        // Existing bindings just get "merged".
+                        let collected = bindings.pop().unwrap().1;
+                        bindings.last_mut().unwrap().1.extend(collected);
+                    }
+                    // This or-pattern itself can itself be part of a product,
+                    // e.g. `(V1(a) | V2(a), a)` or `(a, V1(a) | V2(a))`.
+                    // Both cases bind `a` again in a product pattern and must be rejected.
+                    let collected = bindings.pop().unwrap().1;
+                    bindings.last_mut().unwrap().1.extend(collected);
 
+                    // Prevent visiting `ps` as we've already done so above.
+                    return false;
+                }
                 _ => {}
             }
             true
         });
+    }
 
-        visit::walk_pat(self, pat);
+    fn fresh_binding(
+        &mut self,
+        ident: Ident,
+        pat_id: NodeId,
+        pat_src: PatternSource,
+        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
+    ) -> Res {
+        // Add the binding to the local ribs, if it doesn't already exist in the bindings map.
+        // (We must not add it if it's in the bindings map because that breaks the assumptions
+        // later passes make about or-patterns.)
+        let ident = ident.modern_and_legacy();
+
+        // Walk outwards the stack of products / or-patterns and
+        // find out if the identifier has been bound in any of these.
+        let mut already_bound_and = false;
+        let mut already_bound_or = false;
+        for (is_sum, set) in bindings.iter_mut().rev() {
+            match (is_sum, set.get(&ident).cloned()) {
+                // Already bound in a product pattern, e.g. `(a, a)` which is not allowed.
+                (PatBoundCtx::Product, Some(..)) => already_bound_and = true,
+                // Already bound in an or-pattern, e.g. `V1(a) | V2(a)`.
+                // This is *required* for consistency which is checked later.
+                (PatBoundCtx::Or, Some(..)) => already_bound_or = true,
+                // Not already bound here.
+                _ => {}
+            }
+        }
+
+        if already_bound_and {
+            // Overlap in a product pattern somewhere; report an error.
+            use ResolutionError::*;
+            let error = match pat_src {
+                // `fn f(a: u8, a: u8)`:
+                PatternSource::FnParam => IdentifierBoundMoreThanOnceInParameterList,
+                // `Variant(a, a)`:
+                _ => IdentifierBoundMoreThanOnceInSamePattern,
+            };
+            self.r.report_error(ident.span, error(&ident.as_str()));
+        }
+
+        // Record as bound if it's valid:
+        let ident_valid = ident.name != kw::Invalid;
+        if ident_valid {
+            bindings.last_mut().unwrap().1.insert(ident);
+        }
+
+        if already_bound_or {
+            // `Variant1(a) | Variant2(a)`, ok
+            // Reuse definition from the first `a`.
+            self.innermost_rib_bindings(ValueNS)[&ident]
+        } else {
+            let res = Res::Local(pat_id);
+            if ident_valid {
+                // A completely fresh binding add to the set if it's valid.
+                self.innermost_rib_bindings(ValueNS).insert(ident, res);
+            }
+            res
+        }
+    }
+
+    fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap<Res> {
+        &mut self.ribs[ns].last_mut().unwrap().bindings
+    }
+
+    fn try_resolve_as_non_binding(
+        &mut self,
+        pat_src: PatternSource,
+        pat: &Pat,
+        bm: BindingMode,
+        ident: Ident,
+        has_sub: bool,
+    ) -> Option<Res> {
+        let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?;
+        let res = binding.res();
+
+        // An immutable (no `mut`) by-value (no `ref`) binding pattern without
+        // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
+        // also be interpreted as a path to e.g. a constant, variant, etc.
+        let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Immutable);
+
+        match res {
+            Res::Def(DefKind::Ctor(_, CtorKind::Const), _) |
+            Res::Def(DefKind::Const, _) if is_syntactic_ambiguity => {
+                // Disambiguate in favor of a unit struct/variant or constant pattern.
+                self.r.record_use(ident, ValueNS, binding, false);
+                Some(res)
+            }
+            Res::Def(DefKind::Ctor(..), _)
+            | Res::Def(DefKind::Const, _)
+            | Res::Def(DefKind::Static, _) => {
+                // This is unambiguously a fresh binding, either syntactically
+                // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
+                // to something unusable as a pattern (e.g., constructor function),
+                // but we still conservatively report an error, see
+                // issues/33118#issuecomment-233962221 for one reason why.
+                self.r.report_error(
+                    ident.span,
+                    ResolutionError::BindingShadowsSomethingUnacceptable(
+                        pat_src.descr(),
+                        ident.name,
+                        binding,
+                    ),
+                );
+                None
+            }
+            Res::Def(DefKind::Fn, _) | Res::Err => {
+                // These entities are explicitly allowed to be shadowed by fresh bindings.
+                None
+            }
+            res => {
+                span_bug!(ident.span, "unexpected resolution for an \
+                                        identifier in pattern: {:?}", res);
+            }
+        }
     }
 
     // High-level and context dependent path resolution routine.
@@ -1723,12 +1769,10 @@
         Some(result)
     }
 
-    fn with_resolved_label<F>(&mut self, label: Option<Label>, id: NodeId, f: F)
-        where F: FnOnce(&mut LateResolutionVisitor<'_, '_>)
-    {
+    fn with_resolved_label(&mut self, label: Option<Label>, id: NodeId, f: impl FnOnce(&mut Self)) {
         if let Some(label) = label {
             self.unused_labels.insert(id, label.ident.span);
-            self.with_label_rib(|this| {
+            self.with_label_rib(NormalRibKind, |this| {
                 let ident = label.ident.modern_and_legacy();
                 this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
                 f(this);
@@ -1742,6 +1786,49 @@
         self.with_resolved_label(label, id, |this| this.visit_block(block));
     }
 
+    fn resolve_block(&mut self, block: &Block) {
+        debug!("(resolving block) entering block");
+        // Move down in the graph, if there's an anonymous module rooted here.
+        let orig_module = self.parent_scope.module;
+        let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference
+
+        let mut num_macro_definition_ribs = 0;
+        if let Some(anonymous_module) = anonymous_module {
+            debug!("(resolving block) found anonymous module, moving down");
+            self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module)));
+            self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module)));
+            self.parent_scope.module = anonymous_module;
+        } else {
+            self.ribs[ValueNS].push(Rib::new(NormalRibKind));
+        }
+
+        // Descend into the block.
+        for stmt in &block.stmts {
+            if let StmtKind::Item(ref item) = stmt.node {
+                if let ItemKind::MacroDef(..) = item.node {
+                    num_macro_definition_ribs += 1;
+                    let res = self.r.definitions.local_def_id(item.id);
+                    self.ribs[ValueNS].push(Rib::new(MacroDefinition(res)));
+                    self.label_ribs.push(Rib::new(MacroDefinition(res)));
+                }
+            }
+
+            self.visit_stmt(stmt);
+        }
+
+        // Move back up.
+        self.parent_scope.module = orig_module;
+        for _ in 0 .. num_macro_definition_ribs {
+            self.ribs[ValueNS].pop();
+            self.label_ribs.pop();
+        }
+        self.ribs[ValueNS].pop();
+        if anonymous_module.is_some() {
+            self.ribs[TypeNS].pop();
+        }
+        debug!("(resolving block) leaving block");
+    }
+
     fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
         // First, record candidate traits for this expression if it could
         // result in the invocation of a method call.
@@ -1796,39 +1883,36 @@
                 visit::walk_expr(self, expr);
             }
 
-            ExprKind::Let(ref pats, ref scrutinee) => {
+            ExprKind::Let(ref pat, ref scrutinee) => {
                 self.visit_expr(scrutinee);
-                self.resolve_pats(pats, PatternSource::Let);
+                self.resolve_pattern_top(pat, PatternSource::Let);
             }
 
             ExprKind::If(ref cond, ref then, ref opt_else) => {
-                self.ribs[ValueNS].push(Rib::new(NormalRibKind));
-                self.visit_expr(cond);
-                self.visit_block(then);
-                self.ribs[ValueNS].pop();
-
+                self.with_rib(ValueNS, NormalRibKind, |this| {
+                    this.visit_expr(cond);
+                    this.visit_block(then);
+                });
                 opt_else.as_ref().map(|expr| self.visit_expr(expr));
             }
 
             ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block),
 
-            ExprKind::While(ref subexpression, ref block, label) => {
+            ExprKind::While(ref cond, ref block, label) => {
                 self.with_resolved_label(label, expr.id, |this| {
-                    this.ribs[ValueNS].push(Rib::new(NormalRibKind));
-                    this.visit_expr(subexpression);
-                    this.visit_block(block);
-                    this.ribs[ValueNS].pop();
+                    this.with_rib(ValueNS, NormalRibKind, |this| {
+                        this.visit_expr(cond);
+                        this.visit_block(block);
+                    })
                 });
             }
 
-            ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => {
-                self.visit_expr(subexpression);
-                self.ribs[ValueNS].push(Rib::new(NormalRibKind));
-                self.resolve_pattern(pattern, PatternSource::For, &mut FxHashMap::default());
-
-                self.resolve_labeled_block(label, expr.id, block);
-
-                self.ribs[ValueNS].pop();
+            ExprKind::ForLoop(ref pat, ref iter_expr, ref block, label) => {
+                self.visit_expr(iter_expr);
+                self.with_rib(ValueNS, NormalRibKind, |this| {
+                    this.resolve_pattern_top(pat, PatternSource::For);
+                    this.resolve_labeled_block(label, expr.id, block);
+                });
             }
 
             ExprKind::Block(ref block, label) => self.resolve_labeled_block(label, block.id, block),
@@ -1860,30 +1944,22 @@
             // `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
             // resolve the arguments within the proper scopes so that usages of them inside the
             // closure are detected as upvars rather than normal closure arg usages.
-            ExprKind::Closure(
-                _, IsAsync::Async { .. }, _,
-                ref fn_decl, ref body, _span,
-            ) => {
-                let rib_kind = NormalRibKind;
-                self.ribs[ValueNS].push(Rib::new(rib_kind));
-                // Resolve arguments:
-                let mut bindings_list = FxHashMap::default();
-                for argument in &fn_decl.inputs {
-                    self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
-                    self.visit_ty(&argument.ty);
-                }
-                // No need to resolve return type-- the outer closure return type is
-                // FunctionRetTy::Default
+            ExprKind::Closure(_, IsAsync::Async { .. }, _, ref fn_decl, ref body, _span) => {
+                self.with_rib(ValueNS, NormalRibKind, |this| {
+                    // Resolve arguments:
+                    this.resolve_params(&fn_decl.inputs);
+                    // No need to resolve return type --
+                    // the outer closure return type is `FunctionRetTy::Default`.
 
-                // Now resolve the inner closure
-                {
-                    // No need to resolve arguments: the inner closure has none.
-                    // Resolve the return type:
-                    visit::walk_fn_ret_ty(self, &fn_decl.output);
-                    // Resolve the body
-                    self.visit_expr(body);
-                }
-                self.ribs[ValueNS].pop();
+                    // Now resolve the inner closure
+                    {
+                        // No need to resolve arguments: the inner closure has none.
+                        // Resolve the return type:
+                        visit::walk_fn_ret_ty(this, &fn_decl.output);
+                        // Resolve the body
+                        this.visit_expr(body);
+                    }
+                });
             }
             _ => {
                 visit::walk_expr(self, expr);
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index a822fa0..0c86d84 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -113,7 +113,7 @@
 
         // Emit special messages for unresolved `Self` and `self`.
         if is_self_type(path, ns) {
-            __diagnostic_used!(E0411);
+            syntax::diagnostic_used!(E0411);
             err.code(DiagnosticId::Error("E0411".into()));
             err.span_label(span, format!("`Self` is only available in impls, traits, \
                                           and type definitions"));
@@ -122,7 +122,7 @@
         if is_self_value(path, ns) {
             debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
 
-            __diagnostic_used!(E0424);
+            syntax::diagnostic_used!(E0424);
             err.code(DiagnosticId::Error("E0424".into()));
             err.span_label(span, match source {
                 PathSource::Pat => {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 875ae44..74f68e5 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -9,11 +9,11 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(inner_deref)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
 #![feature(mem_take)]
 #![feature(nll)]
-#![feature(rustc_diagnostic_macros)]
 
 #![recursion_limit="256"]
 
@@ -40,7 +40,7 @@
 use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext};
 use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
 use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives};
-use syntax::symbol::{Symbol, kw, sym};
+use syntax::symbol::{kw, sym};
 
 use syntax::visit::{self, Visitor};
 use syntax::attr;
@@ -67,9 +67,7 @@
 
 type Res = def::Res<NodeId>;
 
-// N.B., this module needs to be declared first so diagnostics are
-// registered before they are used.
-mod error_codes;
+pub mod error_codes;
 mod diagnostics;
 mod late;
 mod macros;
@@ -243,7 +241,7 @@
 
     fn names_to_string(segments: &[Segment]) -> String {
         names_to_string(&segments.iter()
-                            .map(|seg| seg.ident)
+                            .map(|seg| seg.ident.name)
                             .collect::<Vec<_>>())
     }
 }
@@ -537,7 +535,11 @@
     }
 
     fn nearest_item_scope(&'a self) -> Module<'a> {
-        if self.is_trait() { self.parent.unwrap() } else { self }
+        match self.kind {
+            ModuleKind::Def(DefKind::Enum, ..) | ModuleKind::Def(DefKind::Trait, ..) =>
+                self.parent.expect("enum or trait module without a parent"),
+            _ => self,
+        }
     }
 
     fn is_ancestor_of(&self, mut other: &Self) -> bool {
@@ -879,6 +881,10 @@
     /// There will be an anonymous module created around `g` with the ID of the
     /// entry block for `f`.
     block_map: NodeMap<Module<'a>>,
+    /// A fake module that contains no definition and no prelude. Used so that
+    /// some AST passes can generate identifiers that only resolve to local or
+    /// language items.
+    empty_module: Module<'a>,
     module_map: FxHashMap<DefId, Module<'a>>,
     extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>,
     binding_parent_modules: FxHashMap<PtrKey<'a, NameBinding<'a>>, Module<'a>>,
@@ -913,6 +919,7 @@
     non_macro_attrs: [Lrc<SyntaxExtension>; 2],
     macro_defs: FxHashMap<ExpnId, DefId>,
     local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
+    ast_transform_scopes: FxHashMap<ExpnId, Module<'a>>,
     unused_macros: NodeMap<Span>,
     proc_macro_stubs: NodeSet,
     /// Traces collected during macro resolution and validated when it's complete.
@@ -944,7 +951,11 @@
     struct_constructors: DefIdMap<(Res, ty::Visibility)>,
 
     /// Features enabled for this crate.
-    active_features: FxHashSet<Symbol>,
+    active_features: FxHashSet<Name>,
+
+    /// Stores enum visibilities to properly build a reduced graph
+    /// when visiting the correspondent variants.
+    variant_vis: DefIdMap<ty::Visibility>,
 }
 
 /// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -1007,8 +1018,8 @@
     fn resolve_str_path(
         &mut self,
         span: Span,
-        crate_root: Option<Symbol>,
-        components: &[Symbol],
+        crate_root: Option<Name>,
+        components: &[Name],
         ns: Namespace,
     ) -> (ast::Path, Res) {
         let root = if crate_root.is_some() {
@@ -1080,6 +1091,21 @@
             no_implicit_prelude: attr::contains_name(&krate.attrs, sym::no_implicit_prelude),
             ..ModuleData::new(None, root_module_kind, root_def_id, ExpnId::root(), krate.span)
         });
+        let empty_module_kind = ModuleKind::Def(
+            DefKind::Mod,
+            root_def_id,
+            kw::Invalid,
+        );
+        let empty_module = arenas.alloc_module(ModuleData {
+            no_implicit_prelude: true,
+            ..ModuleData::new(
+                Some(graph_root),
+                empty_module_kind,
+                root_def_id,
+                ExpnId::root(),
+                DUMMY_SP,
+            )
+        });
         let mut module_map = FxHashMap::default();
         module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
 
@@ -1139,10 +1165,12 @@
             label_res_map: Default::default(),
             export_map: FxHashMap::default(),
             trait_map: Default::default(),
+            empty_module,
             module_map,
             block_map: Default::default(),
             extern_module_map: FxHashMap::default(),
             binding_parent_modules: FxHashMap::default(),
+            ast_transform_scopes: FxHashMap::default(),
 
             glob_map: Default::default(),
 
@@ -1190,6 +1218,7 @@
                 features.declared_lib_features.iter().map(|(feat, ..)| *feat)
                     .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat))
                     .collect(),
+            variant_vis: Default::default()
         }
     }
 
@@ -1617,7 +1646,7 @@
         }
 
         if let ModuleKind::Block(..) = module.kind {
-            return Some(module.parent.unwrap());
+            return Some(module.parent.unwrap().nearest_item_scope());
         }
 
         None
@@ -2526,7 +2555,7 @@
     fn add_suggestion_for_rename_of_use(
         &self,
         err: &mut DiagnosticBuilder<'_>,
-        name: Symbol,
+        name: Name,
         directive: &ImportDirective<'_>,
         binding_span: Span,
     ) {
@@ -2741,22 +2770,22 @@
     }
 }
 
-fn names_to_string(idents: &[Ident]) -> String {
+fn names_to_string(names: &[Name]) -> String {
     let mut result = String::new();
-    for (i, ident) in idents.iter()
-                            .filter(|ident| ident.name != kw::PathRoot)
+    for (i, name) in names.iter()
+                            .filter(|name| **name != kw::PathRoot)
                             .enumerate() {
         if i > 0 {
             result.push_str("::");
         }
-        result.push_str(&ident.as_str());
+        result.push_str(&name.as_str());
     }
     result
 }
 
 fn path_names_to_string(path: &Path) -> String {
     names_to_string(&path.segments.iter()
-                        .map(|seg| seg.ident)
+                        .map(|seg| seg.ident.name)
                         .collect::<Vec<_>>())
 }
 
@@ -2764,15 +2793,14 @@
 fn module_to_string(module: Module<'_>) -> Option<String> {
     let mut names = Vec::new();
 
-    fn collect_mod(names: &mut Vec<Ident>, module: Module<'_>) {
+    fn collect_mod(names: &mut Vec<Name>, module: Module<'_>) {
         if let ModuleKind::Def(.., name) = module.kind {
             if let Some(parent) = module.parent {
-                names.push(Ident::with_dummy_span(name));
+                names.push(name);
                 collect_mod(names, parent);
             }
         } else {
-            // danger, shouldn't be ident?
-            names.push(Ident::from_str("<opaque>"));
+            names.push(Name::intern("<opaque>"));
             collect_mod(names, module.parent.unwrap());
         }
     }
@@ -2781,9 +2809,8 @@
     if names.is_empty() {
         return None;
     }
-    Some(names_to_string(&names.into_iter()
-                        .rev()
-                        .collect::<Vec<_>>()))
+    names.reverse();
+    Some(names_to_string(&names))
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -2817,5 +2844,3 @@
         }
     }
 }
-
-__build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 7224bd7..3900a3d 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -8,6 +8,7 @@
 use crate::Namespace::*;
 use crate::resolve_imports::ImportResolver;
 use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
+use rustc::hir::def_id;
 use rustc::middle::stability;
 use rustc::{ty, lint, span_bug};
 use syntax::ast::{self, NodeId, Ident};
@@ -15,7 +16,7 @@
 use syntax::edition::Edition;
 use syntax::ext::base::{self, InvocationRes, Indeterminate, SpecialDerives};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
-use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
+use syntax::ext::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind};
 use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind};
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name};
@@ -25,6 +26,7 @@
 
 use std::{mem, ptr};
 use rustc_data_structures::sync::Lrc;
+use syntax_pos::hygiene::AstPass;
 
 type Res = def::Res<NodeId>;
 
@@ -95,16 +97,6 @@
         self.session.next_node_id()
     }
 
-    fn get_module_scope(&mut self, id: NodeId) -> ExpnId {
-        let expn_id = ExpnId::fresh(Some(ExpnData::default(
-            ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, self.session.edition()
-        )));
-        let module = self.module_map[&self.definitions.local_def_id(id)];
-        self.invocation_parent_scopes.insert(expn_id, ParentScope::module(module));
-        self.definitions.set_invocation_parent(expn_id, module.def_id().unwrap().index);
-        expn_id
-    }
-
     fn resolve_dollar_crates(&mut self) {
         hygiene::update_dollar_crate_names(|ctxt| {
             let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
@@ -136,6 +128,37 @@
         }
     }
 
+    // Create a new Expansion with a definition site of the provided module, or
+    // a fake empty `#[no_implicit_prelude]` module if no module is provided.
+    fn expansion_for_ast_pass(
+        &mut self,
+        call_site: Span,
+        pass: AstPass,
+        features: &[Symbol],
+        parent_module_id: Option<NodeId>,
+    ) -> ExpnId {
+        let expn_id = ExpnId::fresh(Some(ExpnData::allow_unstable(
+            ExpnKind::AstPass(pass),
+            call_site,
+            self.session.edition(),
+            features.into(),
+        )));
+
+        let parent_scope = if let Some(module_id) = parent_module_id {
+            let parent_def_id = self.definitions.local_def_id(module_id);
+            self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id);
+            self.module_map[&parent_def_id]
+        } else {
+            self.definitions.add_parent_module_of_macro_def(
+                expn_id,
+                def_id::DefId::local(def_id::CRATE_DEF_INDEX),
+            );
+            self.empty_module
+        };
+        self.ast_transform_scopes.insert(expn_id, parent_scope);
+        expn_id
+    }
+
     fn resolve_imports(&mut self) {
         ImportResolver { r: self }.resolve_imports()
     }
@@ -202,6 +225,27 @@
             self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
         }
 
+        match invoc.fragment_kind {
+            AstFragmentKind::Arms
+                | AstFragmentKind::Fields
+                | AstFragmentKind::FieldPats
+                | AstFragmentKind::GenericParams
+                | AstFragmentKind::Params
+                | AstFragmentKind::StructFields
+                | AstFragmentKind::Variants =>
+            {
+                if let Res::Def(..) = res {
+                    self.session.span_err(
+                        span,
+                        &format!("expected an inert attribute, found {} {}",
+                                 res.article(), res.descr()),
+                    );
+                    return Ok(InvocationRes::Single(self.dummy_ext(kind)));
+                }
+            },
+            _ => {}
+        }
+
         Ok(InvocationRes::Single(ext))
     }
 
@@ -279,7 +323,7 @@
         self.check_stability_and_deprecation(&ext, path);
 
         Ok(if ext.macro_kind() != kind {
-            let expected = if kind == MacroKind::Attr { "attribute" } else  { kind.descr() };
+            let expected = kind.descr_expected();
             let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path);
             self.session.struct_span_err(path.span, &msg)
                         .span_label(path.span, format!("not {} {}", kind.article(), expected))
@@ -730,9 +774,8 @@
                 }
                 Err(..) => {
                     assert!(initial_binding.is_none());
-                    let bang = if kind == MacroKind::Bang { "!" } else { "" };
-                    let msg =
-                        format!("cannot find {} `{}{}` in this scope", kind.descr(), ident, bang);
+                    let expected = kind.descr_expected();
+                    let msg = format!("cannot find {} `{}` in this scope", expected, ident);
                     let mut err = self.session.struct_span_err(ident.span, &msg);
                     self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident);
                     err.emit();
@@ -751,10 +794,10 @@
     fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) {
         let span = path.span;
         if let Some(stability) = &ext.stability {
-            if let StabilityLevel::Unstable { reason, issue } = stability.level {
+            if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
                 let feature = stability.feature;
                 if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
-                    stability::report_unstable(self.session, feature, reason, issue, span);
+                    stability::report_unstable(self.session, feature, reason, issue, is_soft, span);
                 }
             }
             if let Some(depr) = &stability.rustc_depr {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index fd222a1..e77e829 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -71,7 +71,7 @@
 }
 
 /// One import directive.
-#[derive(Debug,Clone)]
+#[derive(Debug, Clone)]
 crate struct ImportDirective<'a> {
     /// The ID of the `extern crate`, `UseTree` etc that imported this `ImportDirective`.
     ///
@@ -447,12 +447,13 @@
     }
 
     // Define the name or return the existing binding if there is a collision.
-    pub fn try_define(&mut self,
-                      module: Module<'a>,
-                      ident: Ident,
-                      ns: Namespace,
-                      binding: &'a NameBinding<'a>)
-                      -> Result<(), &'a NameBinding<'a>> {
+    pub fn try_define(
+        &mut self,
+        module: Module<'a>,
+        ident: Ident,
+        ns: Namespace,
+        binding: &'a NameBinding<'a>,
+    ) -> Result<(), &'a NameBinding<'a>> {
         let res = binding.res();
         self.check_reserved_macro_name(ident, res);
         self.set_binding_parent_module(binding, module);
@@ -480,8 +481,11 @@
                         };
                         if glob_binding.res() != nonglob_binding.res() &&
                            ns == MacroNS && nonglob_binding.expansion != ExpnId::root() {
-                            resolution.binding = Some(this.ambiguity(AmbiguityKind::GlobVsExpanded,
-                                                                    nonglob_binding, glob_binding));
+                            resolution.binding = Some(this.ambiguity(
+                                AmbiguityKind::GlobVsExpanded,
+                                nonglob_binding,
+                                glob_binding,
+                            ));
                         } else {
                             resolution.binding = Some(nonglob_binding);
                         }
@@ -513,9 +517,11 @@
         })
     }
 
-    fn ambiguity(&self, kind: AmbiguityKind,
-                 primary_binding: &'a NameBinding<'a>, secondary_binding: &'a NameBinding<'a>)
-                 -> &'a NameBinding<'a> {
+    fn ambiguity(
+        &self, kind: AmbiguityKind,
+        primary_binding: &'a NameBinding<'a>,
+        secondary_binding: &'a NameBinding<'a>,
+    ) -> &'a NameBinding<'a> {
         self.arenas.alloc_name_binding(NameBinding {
             ambiguity: Some((secondary_binding, kind)),
             ..primary_binding.clone()
@@ -524,8 +530,12 @@
 
     // Use `f` to mutate the resolution of the name in the module.
     // If the resolution becomes a success, define it in the module's glob importers.
-    fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F)
-                               -> T
+    fn update_resolution<T, F>(
+        &mut self, module: Module<'a>,
+        ident: Ident,
+        ns: Namespace,
+        f: F,
+    ) -> T
         where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T
     {
         // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
@@ -627,14 +637,18 @@
             self.finalize_resolutions_in(module);
         }
 
-        let mut has_errors = false;
         let mut seen_spans = FxHashSet::default();
         let mut errors = vec![];
         let mut prev_root_id: NodeId = NodeId::from_u32(0);
-        for i in 0 .. self.r.determined_imports.len() {
-            let import = self.r.determined_imports[i];
+        let determined_imports = mem::take(&mut self.r.determined_imports);
+        let indeterminate_imports = mem::take(&mut self.r.indeterminate_imports);
+
+        for (is_indeterminate, import) in determined_imports
+            .into_iter()
+            .map(|i| (false, i))
+            .chain(indeterminate_imports.into_iter().map(|i| (true, i)))
+        {
             if let Some(err) = self.finalize_import(import) {
-                has_errors = true;
 
                 if let SingleImport { source, ref source_bindings, .. } = import.subclass {
                     if source.name == kw::SelfLower {
@@ -666,21 +680,27 @@
                     errors.push((path, err));
                     prev_root_id = import.root_id;
                 }
+            } else if is_indeterminate {
+                // Consider erroneous imports used to avoid duplicate diagnostics.
+                self.r.used_imports.insert((import.id, TypeNS));
+                let path = import_path_to_string(
+                    &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
+                    &import.subclass,
+                    import.span,
+                );
+                let err = UnresolvedImportError {
+                    span: import.span,
+                    label: None,
+                    note: Vec::new(),
+                    suggestion: None,
+                };
+                errors.push((path, err));
             }
         }
 
         if !errors.is_empty() {
             self.throw_unresolved_import_error(errors.clone(), None);
         }
-
-        // Report unresolved imports only if no hard error was already reported
-        // to avoid generating multiple errors on the same import.
-        if !has_errors {
-            for import in &self.r.indeterminate_imports {
-                self.throw_unresolved_import_error(errors, Some(MultiSpan::from(import.span)));
-                break;
-            }
-        }
     }
 
     fn throw_unresolved_import_error(
@@ -835,10 +855,20 @@
     ) -> Option<UnresolvedImportError> {
         let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
         let prev_ambiguity_errors_len = self.r.ambiguity_errors.len();
-        let path_res = self.r.resolve_path(&directive.module_path, None, &directive.parent_scope,
-                                         true, directive.span, directive.crate_lint());
+        let path_res = self.r.resolve_path(
+            &directive.module_path,
+            None,
+            &directive.parent_scope,
+            true,
+            directive.span,
+            directive.crate_lint(),
+        );
         let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
         directive.vis.set(orig_vis);
+        if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
+            // Consider erroneous imports used to avoid duplicate diagnostics.
+            self.r.used_imports.insert((directive.id, TypeNS));
+        }
         let module = match path_res {
             PathResult::Module(module) => {
                 // Consistency checks, analogous to `finalize_macro_resolutions`.
@@ -895,7 +925,6 @@
                             }
                         }
                     };
-
                     return Some(err);
                 }
                 return None;
@@ -1307,12 +1336,11 @@
                 None => continue,
             };
 
-            // Filter away ambiguous and gensymed imports. Gensymed imports
-            // (e.g. implicitly injected `std`) cannot be properly encoded in metadata,
-            // so they can cause name conflict errors downstream.
-            let is_good_import = binding.is_import() && !binding.is_ambiguity() &&
-                                 // Note that as_str() de-gensyms the Symbol
-                                 !(ident.is_gensymed() && ident.name.as_str() != "_");
+            // Filter away ambiguous imports and anything that has def-site
+            // hygiene.
+            // FIXME: Implement actual cross-crate hygiene.
+            let is_good_import = binding.is_import() && !binding.is_ambiguity()
+                && !ident.span.modern().from_expansion();
             if is_good_import || binding.is_macro_def() {
                 let res = binding.res();
                 if res != Res::Err {
@@ -1405,15 +1433,17 @@
     let global = !names.is_empty() && names[0].name == kw::PathRoot;
     if let Some(pos) = pos {
         let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };
-        names_to_string(names)
+        names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>())
     } else {
         let names = if global { &names[1..] } else { names };
         if names.is_empty() {
             import_directive_subclass_to_string(subclass)
         } else {
-            format!("{}::{}",
-                    names_to_string(names),
-                    import_directive_subclass_to_string(subclass))
+            format!(
+                "{}::{}",
+                names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>()),
+                import_directive_subclass_to_string(subclass),
+            )
         }
     }
 }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index d1fd51a..55f6b91 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -130,6 +130,10 @@
         self.save_ctxt.span_from_span(span)
     }
 
+    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
+        self.save_ctxt.lookup_def_id(ref_id)
+    }
+
     pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
         let source_file = self.tcx.sess.local_crate_source_file.as_ref();
         let crate_root = source_file.map(|source_file| {
@@ -223,13 +227,6 @@
         }
     }
 
-    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
-        match self.save_ctxt.get_path_res(ref_id) {
-            Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => None,
-            def => Some(def.def_id()),
-        }
-    }
-
     fn process_formals(&mut self, formals: &'l [ast::Param], qualname: &str) {
         for arg in formals {
             self.visit_pat(&arg.pat);
@@ -283,36 +280,32 @@
     ) {
         debug!("process_method: {}:{}", id, ident);
 
-        if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) {
-            let sig_str = crate::make_signature(&sig.decl, &generics);
-            if body.is_some() {
-                self.nest_tables(
-                    id,
-                    |v| v.process_formals(&sig.decl.inputs, &method_data.qualname),
-                );
+        let hir_id = self.tcx.hir().node_to_hir_id(id);
+        self.nest_tables(id, |v| {
+            if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) {
+                v.process_formals(&sig.decl.inputs, &method_data.qualname);
+                v.process_generic_params(&generics, &method_data.qualname, id);
+
+                method_data.value = crate::make_signature(&sig.decl, &generics);
+                method_data.sig = sig::method_signature(id, ident, generics, sig, &v.save_ctxt);
+
+                v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, hir_id), method_data);
             }
 
-            self.process_generic_params(&generics, &method_data.qualname, id);
+            // walk arg and return types
+            for arg in &sig.decl.inputs {
+                v.visit_ty(&arg.ty);
+            }
 
-            method_data.value = sig_str;
-            method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt);
-            let hir_id = self.tcx.hir().node_to_hir_id(id);
-            self.dumper.dump_def(&access_from_vis!(self.save_ctxt, vis, hir_id), method_data);
-        }
+            if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
+                v.visit_ty(ret_ty);
+            }
 
-        // walk arg and return types
-        for arg in &sig.decl.inputs {
-            self.visit_ty(&arg.ty);
-        }
-
-        if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
-            self.visit_ty(ret_ty);
-        }
-
-        // walk the fn body
-        if let Some(body) = body {
-            self.nest_tables(id, |v| v.visit_block(body));
-        }
+            // walk the fn body
+            if let Some(body) = body {
+                v.visit_block(body);
+            }
+        });
     }
 
     fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
@@ -377,26 +370,31 @@
         ty_params: &'l ast::Generics,
         body: &'l ast::Block,
     ) {
-        if let Some(fn_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(fn_data, DefData, item.span);
-            self.nest_tables(
-                item.id,
-                |v| v.process_formals(&decl.inputs, &fn_data.qualname),
-            );
-            self.process_generic_params(ty_params, &fn_data.qualname, item.id);
-            let hir_id = self.tcx.hir().node_to_hir_id(item.id);
-            self.dumper.dump_def(&access_from!(self.save_ctxt, item, hir_id), fn_data);
-        }
+        let hir_id = self.tcx.hir().node_to_hir_id(item.id);
+        self.nest_tables(item.id, |v| {
+            if let Some(fn_data) = v.save_ctxt.get_item_data(item) {
+                down_cast_data!(fn_data, DefData, item.span);
+                v.process_formals(&decl.inputs, &fn_data.qualname);
+                v.process_generic_params(ty_params, &fn_data.qualname, item.id);
 
-        for arg in &decl.inputs {
-            self.visit_ty(&arg.ty);
-        }
+                v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), fn_data);
+            }
 
-        if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
-            self.visit_ty(&ret_ty);
-        }
+            for arg in &decl.inputs {
+                v.visit_ty(&arg.ty)
+            }
 
-        self.nest_tables(item.id, |v| v.visit_block(&body));
+            if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
+                if let ast::TyKind::ImplTrait(..) = ret_ty.node {
+                    // FIXME: Opaque type desugaring prevents us from easily
+                    // processing trait bounds. See `visit_ty` for more details.
+                } else {
+                    v.visit_ty(&ret_ty);
+                }
+            }
+
+            v.visit_block(&body);
+        });
     }
 
     fn process_static_or_const_item(
@@ -897,32 +895,23 @@
         }
     }
 
-    fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
+    fn process_var_decl(&mut self, pat: &'l ast::Pat) {
+        // The pattern could declare multiple new vars,
+        // we must walk the pattern and collect them all.
         let mut collector = PathCollector::new();
-        for pattern in pats {
-            // collect paths from the arm's patterns
-            collector.visit_pat(&pattern);
-            self.visit_pat(&pattern);
-        }
+        collector.visit_pat(&pat);
+        self.visit_pat(&pat);
 
-        // process collected paths
-        for (id, ident, immut) in collector.collected_idents {
+        // Process collected paths.
+        for (id, ident, _) in collector.collected_idents {
             match self.save_ctxt.get_path_res(id) {
                 Res::Local(hir_id) => {
-                    let mut value = if immut == ast::Mutability::Immutable {
-                        self.span.snippet(ident.span)
-                    } else {
-                        "<mutable>".to_owned()
-                    };
                     let id = self.tcx.hir().hir_to_node_id(hir_id);
-                    let typ = self.save_ctxt
-                        .tables
-                        .node_type_opt(hir_id)
+                    let typ = self.save_ctxt.tables.node_type_opt(hir_id)
                         .map(|t| t.to_string())
                         .unwrap_or_default();
-                    value.push_str(": ");
-                    value.push_str(&typ);
 
+                    // Rust uses the id of the pattern for var lookups, so we'll use it too.
                     if !self.span.filter_generated(ident.span) {
                         let qualname = format!("{}${}", ident.to_string(), id);
                         let id = id_from_node_id(id, &self.save_ctxt);
@@ -972,61 +961,6 @@
         }
     }
 
-    fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
-        // The local could declare multiple new vars, we must walk the
-        // pattern and collect them all.
-        let mut collector = PathCollector::new();
-        collector.visit_pat(&p);
-        self.visit_pat(&p);
-
-        for (id, ident, immut) in collector.collected_idents {
-            let mut value = match immut {
-                ast::Mutability::Immutable => value.to_string(),
-                _ => String::new(),
-            };
-            let hir_id = self.tcx.hir().node_to_hir_id(id);
-            let typ = match self.save_ctxt.tables.node_type_opt(hir_id) {
-                Some(typ) => {
-                    let typ = typ.to_string();
-                    if !value.is_empty() {
-                        value.push_str(": ");
-                    }
-                    value.push_str(&typ);
-                    typ
-                }
-                None => String::new(),
-            };
-
-            // Rust uses the id of the pattern for var lookups, so we'll use it too.
-            if !self.span.filter_generated(ident.span) {
-                let qualname = format!("{}${}", ident.to_string(), id);
-                let id = id_from_node_id(id, &self.save_ctxt);
-                let span = self.span_from_span(ident.span);
-
-                self.dumper.dump_def(
-                    &Access {
-                        public: false,
-                        reachable: false,
-                    },
-                    Def {
-                        kind: DefKind::Local,
-                        id,
-                        span,
-                        name: ident.to_string(),
-                        qualname,
-                        value: typ,
-                        parent: None,
-                        children: vec![],
-                        decl_id: None,
-                        docs: String::new(),
-                        sig: None,
-                        attributes: vec![],
-                    },
-                );
-            }
-        }
-    }
-
     /// Extracts macro use and definition information from the AST node defined
     /// by the given NodeId, using the expansion information from the node's
     /// span.
@@ -1177,11 +1111,7 @@
                 // FIXME: uses of the assoc type should ideally point to this
                 // 'def' and the name here should be a ref to the def in the
                 // trait.
-                for bound in bounds.iter() {
-                    if let ast::GenericBound::Trait(trait_ref, _) = bound {
-                        self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
-                    }
-                }
+                self.process_bounds(&bounds);
             }
             ast::ImplItemKind::Macro(_) => {}
         }
@@ -1428,10 +1358,10 @@
                 self.visit_ty(&ty);
                 self.process_generic_params(ty_params, &qualname, item.id);
             }
-            OpaqueTy(ref _bounds, ref ty_params) => {
+            OpaqueTy(ref bounds, ref ty_params) => {
                 let qualname = format!("::{}",
                     self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
-                // FIXME do something with _bounds
+
                 let value = String::new();
                 if !self.span.filter_generated(item.ident.span) {
                     let span = self.span_from_span(item.ident.span);
@@ -1457,6 +1387,7 @@
                     );
                 }
 
+                self.process_bounds(bounds);
                 self.process_generic_params(ty_params, &qualname, item.id);
             }
             Mac(_) => (),
@@ -1513,6 +1444,18 @@
                 self.visit_ty(element);
                 self.nest_tables(length.id, |v| v.visit_expr(&length.value));
             }
+            ast::TyKind::ImplTrait(id, ref bounds) => {
+                // FIXME: As of writing, the opaque type lowering introduces
+                // another DefPath scope/segment (used to declare the resulting
+                // opaque type item).
+                // However, the synthetic scope does *not* have associated
+                // typeck tables, which means we can't nest it and we fire an
+                // assertion when resolving the qualified type paths in trait
+                // bounds...
+                // This will panic if called on return type `impl Trait`, which
+                // we guard against in `process_fn`.
+                self.nest_tables(id, |v| v.process_bounds(bounds));
+            }
             _ => visit::walk_ty(self, t),
         }
     }
@@ -1565,14 +1508,13 @@
                 });
             }
             ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) => {
-                let value = self.span.snippet(subexpression.span);
-                self.process_var_decl(pattern, value);
+                self.process_var_decl(pattern);
                 debug!("for loop, walk sub-expr: {:?}", subexpression.node);
                 self.visit_expr(subexpression);
                 visit::walk_block(self, block);
             }
-            ast::ExprKind::Let(ref pats, ref scrutinee) => {
-                self.process_var_decl_multi(pats);
+            ast::ExprKind::Let(ref pat, ref scrutinee) => {
+                self.process_var_decl(pat);
                 self.visit_expr(scrutinee);
             }
             ast::ExprKind::Repeat(ref element, ref count) => {
@@ -1599,7 +1541,7 @@
     }
 
     fn visit_arm(&mut self, arm: &'l ast::Arm) {
-        self.process_var_decl_multi(&arm.pats);
+        self.process_var_decl(&arm.pat);
         if let Some(expr) = &arm.guard {
             self.visit_expr(expr);
         }
@@ -1617,11 +1559,7 @@
 
     fn visit_local(&mut self, l: &'l ast::Local) {
         self.process_macro_use(l.span);
-        let value = l.init
-            .as_ref()
-            .map(|i| self.span.snippet(i.span))
-            .unwrap_or_default();
-        self.process_var_decl(&l.pat, value);
+        self.process_var_decl(&l.pat);
 
         // Just walk the initialiser and type (don't want to walk the pattern again).
         walk_list!(self, visit_ty, &l.ty);
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 92ccd4f..055ccf6 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -1,5 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(nll)]
+#![feature(inner_deref)]
 
 #![recursion_limit="256"]
 
@@ -311,7 +312,7 @@
                     let impl_id = self.next_impl_id();
                     let span = self.span_from_span(sub_span);
 
-                    let type_data = self.lookup_ref_id(typ.id);
+                    let type_data = self.lookup_def_id(typ.id);
                     type_data.map(|type_data| {
                         Data::RelationData(Relation {
                             kind: RelationKind::Impl {
@@ -321,7 +322,7 @@
                             from: id_from_def_id(type_data),
                             to: trait_ref
                                 .as_ref()
-                                .and_then(|t| self.lookup_ref_id(t.ref_id))
+                                .and_then(|t| self.lookup_def_id(t.ref_id))
                                 .map(id_from_def_id)
                                 .unwrap_or_else(|| null_id()),
                         },
@@ -494,7 +495,7 @@
     }
 
     pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option<Ref> {
-        self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| {
+        self.lookup_def_id(trait_ref.ref_id).and_then(|def_id| {
             let span = trait_ref.path.span;
             if generated_code(span) {
                 return None;
@@ -869,7 +870,7 @@
         })
     }
 
-    fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
+    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
         match self.get_path_res(ref_id) {
             Res::PrimTy(_) | Res::SelfTy(..) | Res::Err => None,
             def => Some(def.def_id()),
diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs
index 53364e7..f7551aa 100644
--- a/src/librustc_target/spec/apple_base.rs
+++ b/src/librustc_target/spec/apple_base.rs
@@ -51,3 +51,19 @@
     let (major, minor) = macos_deployment_target();
     format!("{}-apple-macosx{}.{}.0", arch, major, minor)
 }
+
+pub fn macos_link_env_remove() -> Vec<String> {
+    let mut env_remove = Vec::with_capacity(2);
+    // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
+    // may occur when we're linking a custom build script while targeting iOS for example.
+    if let Some(sdkroot) = env::var("SDKROOT").ok() {
+        if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") {
+            env_remove.push("SDKROOT".to_string())
+        }
+    }
+    // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at
+    // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
+    // although this is apparently ignored when using the linker at "/usr/bin/ld".
+    env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".to_string());
+    env_remove
+}
diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs
index 6d3900c..fdbb1bd 100644
--- a/src/librustc_target/spec/apple_ios_base.rs
+++ b/src/librustc_target/spec/apple_ios_base.rs
@@ -38,9 +38,18 @@
     // SDKROOT; for rustc, the user or build system can set it, or we
     // can fall back to checking for xcrun on PATH.)
     if let Some(sdkroot) = env::var("SDKROOT").ok() {
-        let sdkroot_path = Path::new(&sdkroot);
-        if sdkroot_path.is_absolute() && sdkroot_path != Path::new("/") && sdkroot_path.exists() {
-            return Ok(sdkroot);
+        let p = Path::new(&sdkroot);
+        match sdk_name {
+            // Ignore `SDKROOT` if it's clearly set for the wrong platform.
+            "iphoneos" if sdkroot.contains("iPhoneSimulator.platform")
+                       || sdkroot.contains("MacOSX.platform") => (),
+            "iphonesimulator" if sdkroot.contains("iPhoneOS.platform")
+                              || sdkroot.contains("MacOSX.platform") => (),
+            "macosx10.15" if sdkroot.contains("iPhoneOS.platform")
+                          || sdkroot.contains("iPhoneSimulator.platform") => (),
+            // Ignore `SDKROOT` if it's not a valid path.
+            _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (),
+            _ => return Ok(sdkroot),
         }
     }
     let res = Command::new("xcrun")
@@ -100,6 +109,13 @@
     }.to_string()
 }
 
+fn link_env_remove(arch: Arch) -> Vec<String> {
+    match arch {
+        Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
+        X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
+    }
+}
+
 pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
     let pre_link_args = build_pre_link_args(arch)?;
     Ok(TargetOptions {
@@ -107,6 +123,7 @@
         dynamic_linking: false,
         executables: true,
         pre_link_args,
+        link_env_remove: link_env_remove(arch),
         has_elf_tls: false,
         eliminate_frame_pointer: false,
         .. super::apple_base::opts()
diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs
index 7d804ea..27d0582 100644
--- a/src/librustc_target/spec/i686_apple_darwin.rs
+++ b/src/librustc_target/spec/i686_apple_darwin.rs
@@ -5,6 +5,7 @@
     base.cpu = "yonah".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
+    base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
     base.stack_probes = true;
     base.eliminate_frame_pointer = false;
 
diff --git a/src/librustc_target/spec/i686_unknown_uefi.rs b/src/librustc_target/spec/i686_unknown_uefi.rs
new file mode 100644
index 0000000..c60f7b4
--- /dev/null
+++ b/src/librustc_target/spec/i686_unknown_uefi.rs
@@ -0,0 +1,98 @@
+// This defines the ia32 target for UEFI systems as described in the UEFI specification. See the
+// uefi-base module for generic UEFI options. On ia32 systems
+// UEFI systems always run in protected-mode, have the interrupt-controller pre-configured and
+// force a single-CPU execution.
+// The cdecl ABI is used. It differs from the stdcall or fastcall ABI.
+// "i686-unknown-windows" is used to get the minimal subset of windows-specific features.
+
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::uefi_base::opts();
+    base.cpu = "pentium4".to_string();
+    base.max_atomic_width = Some(64);
+
+    // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
+    // enable these CPU features explicitly before their first use, otherwise their instructions
+    // will trigger an exception. Rust does not inject any code that enables AVX/MMX/SSE
+    // instruction sets, so this must be done by the firmware. However, existing firmware is known
+    // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is
+    // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so
+    // far.
+    // If you initialize FP units yourself, you can override these flags with custom linker
+    // arguments, thus giving you access to full MMX/SSE acceleration.
+    base.features = "-mmx,-sse,+soft-float".to_string();
+
+    // UEFI mirrors the calling-conventions used on windows. In case of i686 this means small
+    // structs will be returned as int. This shouldn't matter much, since the restrictions placed
+    // by the UEFI specifications forbid any ABI to return structures.
+    base.abi_return_struct_as_int = true;
+
+    // Use -GNU here, because of the reason below:
+    // Backgound and Problem:
+    //   If we use i686-unknown-windows, the LLVM IA32 MSVC generates compiler intrinsic
+    //   _alldiv, _aulldiv, _allrem, _aullrem, _allmul, which will cause undefined symbol.
+    //   A real issue is __aulldiv() is refered by __udivdi3() - udivmod_inner!(), from
+    //   https://github.com/rust-lang-nursery/compiler-builtins.
+    //   As result, rust-lld generates link error finally.
+    // Root-cause:
+    //   In rust\src\llvm-project\llvm\lib\Target\X86\X86ISelLowering.cpp,
+    //   we have below code to use MSVC intrinsics. It assumes MSVC target
+    //   will link MSVC library. But that is NOT true in UEFI environment.
+    //   UEFI does not link any MSVC or GCC standard library.
+    //      if (Subtarget.isTargetKnownWindowsMSVC() ||
+    //          Subtarget.isTargetWindowsItanium()) {
+    //        // Setup Windows compiler runtime calls.
+    //        setLibcallName(RTLIB::SDIV_I64, "_alldiv");
+    //        setLibcallName(RTLIB::UDIV_I64, "_aulldiv");
+    //        setLibcallName(RTLIB::SREM_I64, "_allrem");
+    //        setLibcallName(RTLIB::UREM_I64, "_aullrem");
+    //        setLibcallName(RTLIB::MUL_I64, "_allmul");
+    //        setLibcallCallingConv(RTLIB::SDIV_I64, CallingConv::X86_StdCall);
+    //        setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::X86_StdCall);
+    //        setLibcallCallingConv(RTLIB::SREM_I64, CallingConv::X86_StdCall);
+    //        setLibcallCallingConv(RTLIB::UREM_I64, CallingConv::X86_StdCall);
+    //        setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::X86_StdCall);
+    //      }
+    //   The compiler intrisics should be implemented by compiler-builtins.
+    //   Unfortunately, compiler-builtins has not provided those intrinsics yet. Such as:
+    //      i386/divdi3.S
+    //      i386/lshrdi3.S
+    //      i386/moddi3.S
+    //      i386/muldi3.S
+    //      i386/udivdi3.S
+    //      i386/umoddi3.S
+    // Possible solution:
+    //   1. Eliminate Intrinsics generation.
+    //      1.1 Choose differnt target to bypass isTargetKnownWindowsMSVC().
+    //      1.2 Remove the "Setup Windows compiler runtime calls" in LLVM
+    //   2. Implement Intrinsics.
+    //   We evaluated all options.
+    //   #2 is hard because we need implement the intrinsics (_aulldiv) generated
+    //   from the other intrinscis (__udivdi3) implementation with the same
+    //   functionality (udivmod_inner). If we let _aulldiv() call udivmod_inner!(),
+    //   then we are in loop. We may have to find another way to implement udivmod_inner!().
+    //   #1.2 may break the existing usage.
+    //   #1.1 seems the simplest solution today.
+    //   The IA32 -gnu calling convention is same as the one defined in UEFI specification.
+    //   It uses cdecl, EAX/ECX/EDX as volatile register, and EAX/EDX as return value.
+    //   We also checked the LLVM X86TargetLowering, the differences between -gnu and -msvc
+    //   is fmodf(f32), longjmp() and TLS. None of them impacts the UEFI code.
+    // As a result, we choose -gnu for i686 version before those intrisics are implemented in
+    // compiler-builtins. After compiler-builtins implements all required intrinsics, we may
+    // remove -gnu and use the default one.
+    Ok(Target {
+        llvm_target: "i686-unknown-windows-gnu".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(),
+        target_os: "uefi".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        arch: "x86".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
+
+        options: base,
+    })
+}
diff --git a/src/librustc_target/spec/linux_kernel_base.rs b/src/librustc_target/spec/linux_kernel_base.rs
new file mode 100644
index 0000000..fae4483
--- /dev/null
+++ b/src/librustc_target/spec/linux_kernel_base.rs
@@ -0,0 +1,26 @@
+use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelroLevel, TargetOptions};
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    let mut pre_link_args = LinkArgs::new();
+    pre_link_args.insert(
+        LinkerFlavor::Gcc,
+        vec!["-Wl,--as-needed".to_string(), "-Wl,-z,noexecstack".to_string()],
+    );
+
+    TargetOptions {
+        disable_redzone: true,
+        panic_strategy: PanicStrategy::Abort,
+        stack_probes: true,
+        eliminate_frame_pointer: false,
+        linker_is_gnu: true,
+        position_independent_executables: true,
+        needs_plt: true,
+        relro_level: RelroLevel::Full,
+        relocation_model: "static".to_string(),
+        target_family: Some("unix".to_string()),
+        pre_link_args,
+
+        ..Default::default()
+    }
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 539e28f..626fa37 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -53,6 +53,7 @@
 mod haiku_base;
 mod hermit_base;
 mod linux_base;
+mod linux_kernel_base;
 mod linux_musl_base;
 mod openbsd_base;
 mod netbsd_base;
@@ -386,6 +387,8 @@
     ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
     ("aarch64-linux-android", aarch64_linux_android),
 
+    ("x86_64-linux-kernel", x86_64_linux_kernel),
+
     ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
     ("armv6-unknown-freebsd", armv6_unknown_freebsd),
     ("armv7-unknown-freebsd", armv7_unknown_freebsd),
@@ -490,6 +493,7 @@
     ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
 
     ("x86_64-unknown-uefi", x86_64_unknown_uefi),
+    ("i686-unknown-uefi", i686_unknown_uefi),
 
     ("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
 
@@ -577,8 +581,10 @@
     /// user-defined libraries.
     pub post_link_args: LinkArgs,
 
-    /// Environment variables to be set before invoking the linker.
+    /// Environment variables to be set for the linker invocation.
     pub link_env: Vec<(String, String)>,
+    /// Environment variables to be removed for the linker invocation.
+    pub link_env_remove: Vec<String>,
 
     /// Extra arguments to pass to the external assembler (when used)
     pub asm_args: Vec<String>,
@@ -840,6 +846,7 @@
             post_link_objects_crt: Vec::new(),
             late_link_args: LinkArgs::new(),
             link_env: Vec::new(),
+            link_env_remove: Vec::new(),
             archive_format: "gnu".to_string(),
             custom_unwind_resume: false,
             allow_asm: true,
@@ -1115,6 +1122,7 @@
         key!(post_link_objects_crt, list);
         key!(post_link_args, link_args);
         key!(link_env, env);
+        key!(link_env_remove, list);
         key!(asm_args, list);
         key!(cpu);
         key!(features);
@@ -1331,6 +1339,7 @@
         target_option_val!(post_link_objects_crt);
         target_option_val!(link_args - post_link_args);
         target_option_val!(env - link_env);
+        target_option_val!(link_env_remove);
         target_option_val!(asm_args);
         target_option_val!(cpu);
         target_option_val!(features);
diff --git a/src/librustc_target/spec/wasm32_wasi.rs b/src/librustc_target/spec/wasm32_wasi.rs
index bb33493..86978c0 100644
--- a/src/librustc_target/spec/wasm32_wasi.rs
+++ b/src/librustc_target/spec/wasm32_wasi.rs
@@ -97,6 +97,10 @@
     options.crt_static_default = true;
     options.crt_static_respected = true;
 
+    // Allow `+crt-static` to create a "cdylib" output which is just a wasm file
+    // without a main function.
+    options.crt_static_allows_dylibs = true;
+
     Ok(Target {
         llvm_target: "wasm32-wasi".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs
index 1821034..d059e44 100644
--- a/src/librustc_target/spec/x86_64_apple_darwin.rs
+++ b/src/librustc_target/spec/x86_64_apple_darwin.rs
@@ -6,6 +6,7 @@
     base.max_atomic_width = Some(128); // core2 support cmpxchg16b
     base.eliminate_frame_pointer = false;
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
+    base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
     base.stack_probes = true;
 
     // Clang automatically chooses a more specific target based on
diff --git a/src/librustc_target/spec/x86_64_linux_kernel.rs b/src/librustc_target/spec/x86_64_linux_kernel.rs
new file mode 100644
index 0000000..a80b021
--- /dev/null
+++ b/src/librustc_target/spec/x86_64_linux_kernel.rs
@@ -0,0 +1,31 @@
+// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for
+// generic Linux kernel options.
+
+use crate::spec::{LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_kernel_base::opts();
+    base.cpu = "x86-64".to_string();
+    base.max_atomic_width = Some(64);
+    base.features =
+        "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
+            .to_string();
+    base.code_model = Some("kernel".to_string());
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+
+    Ok(Target {
+        // FIXME: Some dispute, the linux-on-clang folks think this should use "Linux"
+        llvm_target: "x86_64-elf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        target_os: "none".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        arch: "x86_64".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+
+        options: base,
+    })
+}
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
index ed9c370..f9333e1 100644
--- a/src/librustc_tsan/build.rs
+++ b/src/librustc_tsan/build.rs
@@ -4,6 +4,10 @@
 use cmake::Config;
 
 fn main() {
+    println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
+    if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
+        return;
+    }
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
         build_helper::restore_library_path();
 
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 9e52eae..09e6b76 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -23,6 +23,7 @@
 use crate::require_c_abi_if_c_variadic;
 use smallvec::SmallVec;
 use syntax::ast;
+use syntax::errors::pluralise;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::symbol::sym;
@@ -377,7 +378,7 @@
                     quantifier,
                     bound,
                     kind,
-                    if bound != 1 { "s" } else { "" },
+                    pluralise!(bound),
                 ))
             };
 
@@ -1461,7 +1462,7 @@
         span: Span,
         type_str: &str,
         trait_str: &str,
-        name: &str,
+        name: ast::Name,
     ) {
         let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
         if let (Some(_), Ok(snippet)) = (
@@ -1688,7 +1689,7 @@
                         span,
                         &qself_ty.to_string(),
                         "Trait",
-                        &assoc_ident.as_str(),
+                        assoc_ident.name,
                     );
                 }
                 return Err(ErrorReported);
@@ -1761,7 +1762,7 @@
                 span,
                 "Type",
                 &path_str,
-                &item_segment.ident.as_str(),
+                item_segment.ident.name,
             );
             return tcx.types.err;
         };
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index efc37cc..308a3d8 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -2,7 +2,8 @@
 use crate::check::coercion::CoerceMany;
 use rustc::hir::{self, ExprKind};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc::traits::{ObligationCause, ObligationCauseCode};
+use rustc::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
+use rustc::traits::{ObligationCauseCode};
 use rustc::ty::Ty;
 use syntax_pos::Span;
 
@@ -112,19 +113,26 @@
             }
 
             self.diverges.set(pats_diverge);
-            let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
+            let arm_ty = if source_if && if_no_else && i != 0 && self.if_fallback_coercion(
+                expr.span,
+                &arms[0].body,
+                &mut coercion,
+            ) {
+                tcx.types.err
+            } else {
+                // Only call this if this is not an `if` expr with an expected type and no `else`
+                // clause to avoid duplicated type errors. (#60254)
+                self.check_expr_with_expectation(&arm.body, expected)
+            };
             all_arms_diverge &= self.diverges.get();
-
-            let span = expr.span;
-
             if source_if {
                 let then_expr = &arms[0].body;
                 match (i, if_no_else) {
-                    (0, _) => coercion.coerce(self, &self.misc(span), &arm.body, arm_ty),
-                    (_, true) => self.if_fallback_coercion(span, then_expr, &mut coercion),
+                    (0, _) => coercion.coerce(self, &self.misc(expr.span), &arm.body, arm_ty),
+                    (_, true) => {} // Handled above to avoid duplicated type errors (#60254).
                     (_, _) => {
                         let then_ty = prior_arm_ty.unwrap();
-                        let cause = self.if_cause(span, then_expr, &arm.body, then_ty, arm_ty);
+                        let cause = self.if_cause(expr.span, then_expr, &arm.body, then_ty, arm_ty);
                         coercion.coerce(self, &cause, &arm.body, arm_ty);
                     }
                 }
@@ -139,13 +147,15 @@
                     // The reason for the first arm to fail is not that the match arms diverge,
                     // but rather that there's a prior obligation that doesn't hold.
                     0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)),
-                    _ => (span, ObligationCauseCode::MatchExpressionArm {
-                        arm_span,
-                        source: match_src,
-                        prior_arms: other_arms.clone(),
-                        last_ty: prior_arm_ty.unwrap(),
-                        discrim_hir_id: discrim.hir_id,
-                    }),
+                    _ => (expr.span,
+                          ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                            arm_span,
+                            source: match_src,
+                            prior_arms: other_arms.clone(),
+                            last_ty: prior_arm_ty.unwrap(),
+                            discrim_hir_id: discrim.hir_id,
+                          })
+                         ),
                 };
                 let cause = self.cause(span, code);
                 coercion.coerce(self, &cause, &arm.body, arm_ty);
@@ -180,16 +190,19 @@
     }
 
     /// Handle the fallback arm of a desugared if(-let) like a missing else.
+    ///
+    /// Returns `true` if there was an error forcing the coercion to the `()` type.
     fn if_fallback_coercion(
         &self,
         span: Span,
         then_expr: &'tcx hir::Expr,
         coercion: &mut CoerceMany<'tcx, '_, rustc::hir::Arm>,
-    ) {
+    ) -> bool {
         // If this `if` expr is the parent's function return expr,
         // the cause of the type coercion is the return type, point at it. (#25228)
         let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span);
         let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse);
+        let mut error = false;
         coercion.coerce_forced_unit(self, &cause, &mut |err| {
             if let Some((span, msg)) = &ret_reason {
                 err.span_label(*span, msg.as_str());
@@ -200,7 +213,9 @@
             }
             err.note("`if` expressions without `else` evaluate to `()`");
             err.help("consider adding an `else` block that evaluates to the expected type");
+            error = true;
         }, ret_reason.is_none());
+        error
     }
 
     fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> {
@@ -333,11 +348,11 @@
         };
 
         // Finally construct the cause:
-        self.cause(error_sp, ObligationCauseCode::IfExpression {
+        self.cause(error_sp, ObligationCauseCode::IfExpression(box IfExpressionCause {
             then: then_sp,
             outer: outer_sp,
             semicolon: remove_semicolon,
-        })
+        }))
     }
 
     fn demand_discriminant_type(
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 55e7a10..c216cc9 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -40,6 +40,7 @@
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::cast::{CastKind, CastTy};
+use rustc::ty::error::TypeError;
 use rustc::middle::lang_items;
 use syntax::ast;
 use syntax_pos::Span;
@@ -461,6 +462,9 @@
                                              self.expr_ty,
                                              fcx.tcx.mk_fn_ptr(f),
                                              AllowTwoPhase::No);
+                    if let Err(TypeError::IntrinsicCast) = res {
+                        return Err(CastError::IllegalCast);
+                    }
                     if res.is_err() {
                         return Err(CastError::NonScalar);
                     }
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index e937042..d626bff 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -529,11 +529,11 @@
                 ); // recreated from (*) above
 
                 // Check that E' = S'.
-                let cause = &self.misc(hir_ty.span);
+                let cause = self.misc(hir_ty.span);
                 let InferOk {
                     value: (),
                     obligations,
-                } = self.at(cause, self.param_env)
+                } = self.at(&cause, self.param_env)
                     .eq(*expected_ty, supplied_ty)?;
                 all_obligations.extend(obligations);
 
@@ -549,7 +549,7 @@
                 );
                 all_obligations.push(
                     Obligation::new(
-                        cause.clone(),
+                        cause,
                         self.param_env,
                         ty::Predicate::TypeOutlives(
                             ty::Binder::dummy(
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 61b9c2a..f2e1a6e 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -70,6 +70,7 @@
 use syntax::feature_gate;
 use syntax::symbol::sym;
 use syntax_pos;
+use rustc_target::spec::abi::Abi;
 
 struct Coerce<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
@@ -689,6 +690,11 @@
         match b.sty {
             ty::FnPtr(_) => {
                 let a_sig = a.fn_sig(self.tcx);
+                // Intrinsics are not coercible to function pointers
+                if a_sig.abi() == Abi::RustIntrinsic ||
+                   a_sig.abi() == Abi::PlatformIntrinsic {
+                   return Err(TypeError::IntrinsicCast);
+                }
                 let InferOk { value: a_sig, mut obligations } =
                     self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);
 
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 8e187b7..51adf50 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -10,6 +10,7 @@
 use errors::{Applicability, DiagnosticId};
 
 use syntax_pos::Span;
+use syntax::errors::pluralise;
 
 use super::{Inherited, FnCtxt, potentially_plural_count};
 
@@ -308,7 +309,7 @@
 
             let cause = ObligationCause {
                 span: impl_err_span,
-                ..cause.clone()
+                ..cause
             };
 
             let mut diag = struct_span_err!(tcx.sess,
@@ -648,9 +649,9 @@
                      declaration has {} {kind} parameter{}",
                     trait_.ident,
                     impl_count,
-                    if impl_count != 1 { "s" } else { "" },
+                    pluralise!(impl_count),
                     trait_count,
-                    if trait_count != 1 { "s" } else { "" },
+                    pluralise!(trait_count),
                     kind = kind,
                 ),
                 DiagnosticId::Error("E0049".into()),
@@ -665,7 +666,7 @@
                         "expected {} {} parameter{}",
                         trait_count,
                         kind,
-                        if trait_count != 1 { "s" } else { "" },
+                        pluralise!(trait_count),
                     ));
                 }
                 for span in spans {
@@ -680,7 +681,7 @@
                     "found {} {} parameter{}{}",
                     impl_count,
                     kind,
-                    if impl_count != 1 { "s" } else { "" },
+                    pluralise!(impl_count),
                     suffix.unwrap_or_else(|| String::new()),
                 ));
             }
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index d139cd4..56bd903 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -12,14 +12,14 @@
 use crate::check::report_unexpected_variant_res;
 use crate::check::Needs;
 use crate::check::TupleArgumentsFlag::DontTupleArguments;
-use crate::check::method::SelfSource;
+use crate::check::method::{probe, SelfSource, MethodError};
 use crate::util::common::ErrorReported;
 use crate::util::nodemap::FxHashMap;
 use crate::astconv::AstConv as _;
 
 use errors::{Applicability, DiagnosticBuilder};
 use syntax::ast;
-use syntax::symbol::{Symbol, LocalInternedString, kw, sym};
+use syntax::symbol::{Symbol, kw, sym};
 use syntax::source_map::Span;
 use syntax::util::lev_distance::find_best_match_for_name;
 use rustc::hir;
@@ -29,6 +29,7 @@
 use rustc::hir::ptr::P;
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc::middle::lang_items;
 use rustc::mir::interpret::GlobalId;
 use rustc::ty;
 use rustc::ty::adjustment::{
@@ -160,6 +161,10 @@
         // Warn for non-block expressions with diverging children.
         match expr.node {
             ExprKind::Block(..) | ExprKind::Loop(..) | ExprKind::Match(..) => {},
+            ExprKind::Call(ref callee, _) =>
+                self.warn_if_unreachable(expr.hir_id, callee.span, "call"),
+            ExprKind::MethodCall(_, ref span, _) =>
+                self.warn_if_unreachable(expr.hir_id, *span, "call"),
             _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"),
         }
 
@@ -775,35 +780,75 @@
         // no need to check for bot/err -- callee does that
         let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t);
 
-        let method = match self.lookup_method(rcvr_t,
-                                              segment,
-                                              span,
-                                              expr,
-                                              rcvr) {
+        let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr) {
             Ok(method) => {
                 self.write_method_call(expr.hir_id, method);
                 Ok(method)
             }
             Err(error) => {
                 if segment.ident.name != kw::Invalid {
-                    self.report_method_error(span,
-                                             rcvr_t,
-                                             segment.ident,
-                                             SelfSource::MethodCall(rcvr),
-                                             error,
-                                             Some(args));
+                    self.report_extended_method_error(segment, span, args, rcvr_t, error);
                 }
                 Err(())
             }
         };
 
         // Call the generic checker.
-        self.check_method_argument_types(span,
-                                         expr.span,
-                                         method,
-                                         &args[1..],
-                                         DontTupleArguments,
-                                         expected)
+        self.check_method_argument_types(
+            span,
+            expr.span,
+            method,
+            &args[1..],
+            DontTupleArguments,
+            expected,
+        )
+    }
+
+    fn report_extended_method_error(
+        &self,
+        segment: &hir::PathSegment,
+        span: Span,
+        args: &'tcx [hir::Expr],
+        rcvr_t: Ty<'tcx>,
+        error: MethodError<'tcx>
+    ) {
+        let rcvr = &args[0];
+        let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, rcvr_t, lang_item| {
+            if let Some(new_rcvr_t) = self.tcx.mk_lang_item(rcvr_t, lang_item) {
+                if let Ok(pick) = self.lookup_probe(
+                    span,
+                    segment.ident,
+                    new_rcvr_t,
+                    rcvr,
+                    probe::ProbeScope::AllTraits,
+                ) {
+                    err.span_label(
+                        pick.item.ident.span,
+                        &format!("the method is available for `{}` here", new_rcvr_t),
+                    );
+                }
+            }
+        };
+
+        if let Some(mut err) = self.report_method_error(
+            span,
+            rcvr_t,
+            segment.ident,
+            SelfSource::MethodCall(rcvr),
+            error,
+            Some(args),
+        ) {
+            if let ty::Adt(..) = rcvr_t.sty {
+                // Try alternative arbitrary self types that could fulfill this call.
+                // FIXME: probe for all types that *could* be arbitrary self-types, not
+                // just this whitelist.
+                try_alt_rcvr(&mut err, rcvr_t, lang_items::OwnedBoxLangItem);
+                try_alt_rcvr(&mut err, rcvr_t, lang_items::PinTypeLangItem);
+                try_alt_rcvr(&mut err, rcvr_t, lang_items::Arc);
+                try_alt_rcvr(&mut err, rcvr_t, lang_items::Rc);
+            }
+            err.emit();
+        }
     }
 
     fn check_expr_cast(
@@ -1198,7 +1243,7 @@
             }
             _ => {
                 // prevent all specified fields from being suggested
-                let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str());
+                let skip_fields = skip_fields.iter().map(|ref x| x.ident.name);
                 if let Some(field_name) = Self::suggest_field_name(
                     variant,
                     &field.ident.as_str(),
@@ -1242,11 +1287,11 @@
     // Return an hint about the closest match in field names
     fn suggest_field_name(variant: &'tcx ty::VariantDef,
                           field: &str,
-                          skip: Vec<LocalInternedString>)
+                          skip: Vec<Symbol>)
                           -> Option<Symbol> {
         let names = variant.fields.iter().filter_map(|field| {
             // ignore already set fields and private fields from non-local crates
-            if skip.iter().any(|x| *x == field.ident.as_str()) ||
+            if skip.iter().any(|&x| x == field.ident.name) ||
                (!variant.def_id.is_local() && field.vis != Visibility::Public)
             {
                 None
@@ -1392,12 +1437,17 @@
         base_did: DefId,
     ) {
         let struct_path = self.tcx().def_path_str(base_did);
+        let kind_name = match self.tcx().def_kind(base_did) {
+            Some(def_kind) => def_kind.descr(base_did),
+            _ => " ",
+        };
         let mut err = struct_span_err!(
             self.tcx().sess,
             expr.span,
             E0616,
-            "field `{}` of struct `{}` is private",
+            "field `{}` of {} `{}` is private",
             field,
+            kind_name,
             struct_path
         );
         // Also check if an accessible method exists, which is often what is meant.
@@ -1461,8 +1511,10 @@
             let struct_variant_def = def.non_enum_variant();
             let field_names = self.available_field_names(struct_variant_def);
             if !field_names.is_empty() {
-                err.note(&format!("available fields are: {}",
-                                    self.name_series_display(field_names)));
+                err.note(&format!(
+                    "available fields are: {}",
+                    self.name_series_display(field_names),
+                ));
             }
         }
     }
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index a7e4f8e..1509c0f 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -245,7 +245,7 @@
         Ok(result.callee)
     }
 
-    fn lookup_probe(
+    pub fn lookup_probe(
         &self,
         span: Span,
         method_name: ast::Ident,
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 1c01c84..c883831 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -578,6 +578,10 @@
             ty::Param(p) => {
                 self.assemble_inherent_candidates_from_param(p);
             }
+            ty::Bool => {
+                let lang_def_id = lang_items.bool_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
+            }
             ty::Char => {
                 let lang_def_id = lang_items.char_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 440e7e5..3e45b1e 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -69,12 +69,12 @@
         source: SelfSource<'b>,
         error: MethodError<'tcx>,
         args: Option<&'tcx [hir::Expr]>,
-    ) {
+    ) -> Option<DiagnosticBuilder<'_>> {
         let orig_span = span;
         let mut span = span;
         // Avoid suggestions when we don't know what's going on.
         if rcvr_ty.references_error() {
-            return;
+            return None;
         }
 
         let print_disambiguation_help = |
@@ -314,7 +314,7 @@
                             _ => {}
                         }
                         err.emit();
-                        return;
+                        return None;
                     } else {
                         span = item_name.span;
                         let mut err = struct_span_err!(
@@ -425,6 +425,9 @@
                             "private field"
                         };
                         err.span_label(item_name.span, format!("{}, not a method", field_kind));
+                    } else if lev_candidate.is_none() && static_sources.is_empty() {
+                        err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
+                        self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
                     }
                 } else {
                     err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
@@ -529,7 +532,7 @@
                     );
                 }
 
-                err.emit();
+                return Some(err);
             }
 
             MethodError::Ambiguity(sources) => {
@@ -573,6 +576,7 @@
                 bug!("no return type expectations but got BadReturnType")
             }
         }
+        None
     }
 
     fn suggest_use_candidates(&self,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a805504..1197160 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -400,7 +400,7 @@
 
 impl UnsafetyState {
     pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
-        UnsafetyState { def: def, unsafety: unsafety, unsafe_push_count: 0, from_fn: true }
+        UnsafetyState { def, unsafety, unsafe_push_count: 0, from_fn: true }
     }
 
     pub fn recurse(&mut self, blk: &hir::Block) -> UnsafetyState {
@@ -1088,6 +1088,8 @@
 
     let span = body.value.span;
 
+    fn_maybe_err(fcx.tcx, span, fn_sig.abi);
+
     if body.generator_kind.is_some() && can_be_generator.is_some() {
         let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
             kind: TypeVariableOriginKind::TypeInference,
@@ -1420,8 +1422,8 @@
                 tcx.sess, span, E0733,
                 "recursion in an `async fn` requires boxing",
             )
-            .span_label(span, "an `async fn` cannot invoke itself directly")
-            .note("a recursive `async fn` must be rewritten to return a boxed future.")
+            .span_label(span, "recursive `async fn`")
+            .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`.")
             .emit();
         } else {
             let mut err = struct_span_err!(
@@ -1439,6 +1441,14 @@
     }
 }
 
+// Forbid defining intrinsics in Rust code,
+// as they must always be defined by the compiler.
+fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
+    if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
+        tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block");
+    }
+}
+
 pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item) {
     debug!(
         "check_item_type(it.hir_id={}, it.name={})",
@@ -1475,9 +1485,17 @@
                 check_on_unimplemented(tcx, trait_def_id, it);
             }
         }
-        hir::ItemKind::Trait(..) => {
+        hir::ItemKind::Trait(_, _, _, _, ref items) => {
             let def_id = tcx.hir().local_def_id(it.hir_id);
             check_on_unimplemented(tcx, def_id, it);
+
+            for item in items.iter() {
+                let item = tcx.hir().trait_item(item.id);
+                if let hir::TraitItemKind::Method(sig, _) = &item.node {
+                    let abi = sig.header.abi;
+                    fn_maybe_err(tcx, item.ident.span, abi);
+                }
+            }
         }
         hir::ItemKind::Struct(..) => {
             check_struct(tcx, it.hir_id, it.span);
@@ -1511,21 +1529,34 @@
             } else {
                 for item in &m.items {
                     let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
-                    if generics.params.len() - generics.own_counts().lifetimes != 0 {
-                        let mut err = struct_span_err!(
+                    let own_counts = generics.own_counts();
+                    if generics.params.len() - own_counts.lifetimes != 0 {
+                        let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) {
+                            (_, 0) => ("type", "types", Some("u32")),
+                            // We don't specify an example value, because we can't generate
+                            // a valid value for any type.
+                            (0, _) => ("const", "consts", None),
+                            _ => ("type or const", "types or consts", None),
+                        };
+                        struct_span_err!(
                             tcx.sess,
                             item.span,
                             E0044,
-                            "foreign items may not have type parameters"
-                        );
-                        err.span_label(item.span, "can't have type parameters");
-                        // FIXME: once we start storing spans for type arguments, turn this into a
-                        // suggestion.
-                        err.help(
-                            "use specialization instead of type parameters by replacing them \
-                             with concrete types like `u32`",
-                        );
-                        err.emit();
+                            "foreign items may not have {} parameters",
+                            kinds,
+                        ).span_label(
+                            item.span,
+                            &format!("can't have {} parameters", kinds),
+                        ).help(
+                            // FIXME: once we start storing spans for type arguments, turn this
+                            // into a suggestion.
+                            &format!(
+                                "replace the {} parameters with concrete {}{}",
+                                kinds,
+                                kinds_pl,
+                                egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
+                            ),
+                        ).emit();
                     }
 
                     if let hir::ForeignItemKind::Fn(ref fn_decl, _, _) = item.node {
@@ -1570,7 +1601,7 @@
         } else {
             bug!("Matching on non-ByRef static")
         };
-        if alloc.relocations.len() != 0 {
+        if alloc.relocations().len() != 0 {
             let msg = "statics with a custom `#[link_section]` must be a \
                        simple list of bytes on the wasm target with no \
                        extra levels of indirection such as references";
@@ -3580,7 +3611,7 @@
                     SelfSource::QPath(qself),
                     error,
                     None,
-                );
+                ).map(|mut e| e.emit());
             }
             result
         });
@@ -3687,6 +3718,40 @@
         }
     }
 
+    /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
+    /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors
+    /// when given code like the following:
+    /// ```text
+    /// if false { return 0i32; } else { 1u32 }
+    /// //                               ^^^^ point at this instead of the whole `if` expression
+    /// ```
+    fn get_expr_coercion_span(&self, expr: &hir::Expr) -> syntax_pos::Span {
+        if let hir::ExprKind::Match(_, arms, _) = &expr.node {
+            let arm_spans: Vec<Span> = arms.iter().filter_map(|arm| {
+                self.in_progress_tables
+                    .and_then(|tables| tables.borrow().node_type_opt(arm.body.hir_id))
+                    .and_then(|arm_ty| {
+                        if arm_ty.is_never() {
+                            None
+                        } else {
+                            Some(match &arm.body.node {
+                                // Point at the tail expression when possible.
+                                hir::ExprKind::Block(block, _) => block.expr
+                                    .as_ref()
+                                    .map(|e| e.span)
+                                    .unwrap_or(block.span),
+                                _ => arm.body.span,
+                            })
+                        }
+                    })
+            }).collect();
+            if arm_spans.len() == 1 {
+                return arm_spans[0];
+            }
+        }
+        expr.span
+    }
+
     fn check_block_with_expected(
         &self,
         blk: &'tcx hir::Block,
@@ -3746,12 +3811,9 @@
             let coerce = ctxt.coerce.as_mut().unwrap();
             if let Some(tail_expr_ty) = tail_expr_ty {
                 let tail_expr = tail_expr.unwrap();
-                let cause = self.cause(tail_expr.span,
-                                       ObligationCauseCode::BlockTailExpression(blk.hir_id));
-                coerce.coerce(self,
-                              &cause,
-                              tail_expr,
-                              tail_expr_ty);
+                let span = self.get_expr_coercion_span(tail_expr);
+                let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
+                coerce.coerce(self, &cause, tail_expr, tail_expr_ty);
             } else {
                 // Subtle: if there is no explicit tail expression,
                 // that is typically equivalent to a tail expression
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 93855a3..18b555d 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -268,7 +268,7 @@
                                 op.node.as_str(), lhs_ty),
                             );
                             let mut suggested_deref = false;
-                            if let Ref(_, mut rty, _) = lhs_ty.sty {
+                            if let Ref(_, rty, _) = lhs_ty.sty {
                                 if {
                                     self.infcx.type_is_copy_modulo_regions(self.param_env,
                                                                            rty,
@@ -279,13 +279,10 @@
                                             .is_ok()
                                 } {
                                     if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
-                                        while let Ref(_, rty_inner, _) = rty.sty {
-                                            rty = rty_inner;
-                                        }
                                         let msg = &format!(
                                             "`{}=` can be used on '{}', you can dereference `{}`",
                                             op.node.as_str(),
-                                            rty,
+                                            rty.peel_refs(),
                                             lstring,
                                         );
                                         err.span_suggestion(
@@ -361,7 +358,7 @@
                             }
 
                             let mut suggested_deref = false;
-                            if let Ref(_, mut rty, _) = lhs_ty.sty {
+                            if let Ref(_, rty, _) = lhs_ty.sty {
                                 if {
                                     self.infcx.type_is_copy_modulo_regions(self.param_env,
                                                                            rty,
@@ -372,17 +369,13 @@
                                             .is_ok()
                                 } {
                                     if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
-                                        while let Ref(_, rty_inner, _) = rty.sty {
-                                            rty = rty_inner;
-                                        }
-                                        let msg = &format!(
-                                                "`{}` can be used on '{}', you can \
-                                                dereference `{2}`: `*{2}`",
-                                                op.node.as_str(),
-                                                rty,
-                                                lstring
-                                        );
-                                        err.help(msg);
+                                        err.help(&format!(
+                                            "`{}` can be used on '{}', you can \
+                                            dereference `{2}`: `*{2}`",
+                                            op.node.as_str(),
+                                            rty.peel_refs(),
+                                            lstring
+                                        ));
                                         suggested_deref = true;
                                     }
                                 }
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 4cf0df3..8502b89 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -675,21 +675,39 @@
                 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
             }
         } else {
-            let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
-            let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
-            struct_span_err!(tcx.sess, pat.span, E0023,
-                             "this pattern has {} field{}, but the corresponding {} has {} field{}",
-                             subpats.len(), subpats_ending, res.descr(),
-                             variant.fields.len(),  fields_ending)
-                .span_label(pat.span, format!("expected {} field{}, found {}",
-                                              variant.fields.len(), fields_ending, subpats.len()))
-                .emit();
+            // Pattern has wrong number of fields.
+            self.e0023(pat.span, res, &subpats, &variant.fields);
             on_error();
             return tcx.types.err;
         }
         pat_ty
     }
 
+    fn e0023(&self, pat_span: Span, res: Res, subpats: &'tcx [P<Pat>], fields: &[ty::FieldDef]) {
+        let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
+        let fields_ending = if fields.len() == 1 { "" } else { "s" };
+        let res_span = self.tcx.def_span(res.def_id());
+        struct_span_err!(
+            self.tcx.sess,
+            pat_span,
+            E0023,
+            "this pattern has {} field{}, but the corresponding {} has {} field{}",
+            subpats.len(),
+            subpats_ending,
+            res.descr(),
+            fields.len(),
+            fields_ending,
+        )
+            .span_label(pat_span, format!(
+                "expected {} field{}, found {}",
+                fields.len(),
+                fields_ending,
+                subpats.len(),
+            ))
+            .span_label(res_span, format!("{} defined here", res.descr()))
+            .emit();
+    }
+
     fn check_pat_tuple(
         &self,
         span: Span,
@@ -1080,22 +1098,35 @@
 
     fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
         struct_span_err!(
-            self.tcx.sess, span, E0527,
-            "pattern requires {} elements but array has {}",
-            min_len, size
+            self.tcx.sess,
+            span,
+            E0527,
+            "pattern requires {} element{} but array has {}",
+            min_len,
+            if min_len != 1 { "s" } else { "" },
+            size,
         )
-        .span_label(span, format!("expected {} elements", size))
+        .span_label(span, format!("expected {} element{}", size, if size != 1 { "s" } else { "" }))
         .emit();
     }
 
     fn error_scrutinee_with_rest_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
         struct_span_err!(
-            self.tcx.sess, span, E0528,
-            "pattern requires at least {} elements but array has {}",
-            min_len, size
-        )
-        .span_label(span, format!("pattern cannot match array of {} elements", size))
-        .emit();
+            self.tcx.sess,
+            span,
+            E0528,
+            "pattern requires at least {} element{} but array has {}",
+            min_len,
+            if min_len != 1 { "s" } else { "" },
+            size,
+        ).span_label(
+            span,
+            format!(
+                "pattern cannot match array of {} element{}",
+                size,
+                if size != 1 { "s" } else { "" },
+            ),
+        ).emit();
     }
 
     fn error_scrutinee_unfixed_length(&self, span: Span) {
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index f95b3e4..ac8ee43 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -762,19 +762,19 @@
     substituted_predicates
 }
 
+const HELP_FOR_SELF_TYPE: &str =
+    "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
+     `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
+     of the previous types except `Self`)";
+
 fn check_method_receiver<'fcx, 'tcx>(
     fcx: &FnCtxt<'fcx, 'tcx>,
     method_sig: &hir::MethodSig,
     method: &ty::AssocItem,
     self_ty: Ty<'tcx>,
 ) {
-    const HELP_FOR_SELF_TYPE: &str =
-        "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
-         `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
-         of the previous types except `Self`)";
     // Check that the method has a valid receiver type, given the type `Self`.
-    debug!("check_method_receiver({:?}, self_ty={:?})",
-           method, self_ty);
+    debug!("check_method_receiver({:?}, self_ty={:?})", method, self_ty);
 
     if !method.method_has_self_argument {
         return;
@@ -805,12 +805,7 @@
     if fcx.tcx.features().arbitrary_self_types {
         if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
             // Report error; `arbitrary_self_types` was enabled.
-            fcx.tcx.sess.diagnostic().mut_span_err(
-                span, &format!("invalid method receiver type: {:?}", receiver_ty)
-            ).note("type of `self` must be `Self` or a type that dereferences to it")
-            .help(HELP_FOR_SELF_TYPE)
-            .code(DiagnosticId::Error("E0307".into()))
-            .emit();
+            e0307(fcx, span, receiver_ty);
         }
     } else {
         if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) {
@@ -830,17 +825,22 @@
                 .emit();
             } else {
                 // Report error; would not have worked with `arbitrary_self_types`.
-                fcx.tcx.sess.diagnostic().mut_span_err(
-                    span, &format!("invalid method receiver type: {:?}", receiver_ty)
-                ).note("type must be `Self` or a type that dereferences to it")
-                .help(HELP_FOR_SELF_TYPE)
-                .code(DiagnosticId::Error("E0307".into()))
-                .emit();
+                e0307(fcx, span, receiver_ty);
             }
         }
     }
 }
 
+fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) {
+    fcx.tcx.sess.diagnostic().mut_span_err(
+        span,
+        &format!("invalid `self` parameter type: {:?}", receiver_ty)
+    ).note("type of `self` must be `Self` or a type that dereferences to it")
+    .help(HELP_FOR_SELF_TYPE)
+    .code(DiagnosticId::Error("E0307".into()))
+    .emit();
+}
+
 /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
 /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
 /// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index fb79a85..e7c2126 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -67,6 +67,14 @@
             ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => {
                 self.check_def_id(item, data.principal_def_id().unwrap());
             }
+            ty::Bool => {
+                self.check_primitive_impl(def_id,
+                                          lang_items.bool_impl(),
+                                          None,
+                                          "bool",
+                                          "bool",
+                                          item.span);
+            }
             ty::Char => {
                 self.check_primitive_impl(def_id,
                                           lang_items.char_impl(),
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 312a598..d2e9203 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -519,15 +519,15 @@
     tcx.predicates_of(def_id);
 }
 
-fn convert_enum_variant_types<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn convert_enum_variant_types(
+    tcx: TyCtxt<'_>,
     def_id: DefId,
     variants: &[hir::Variant]
 ) {
     let def = tcx.adt_def(def_id);
     let repr_type = def.repr.discr_type();
     let initial = repr_type.initial_discriminant(tcx);
-    let mut prev_discr = None::<Discr<'tcx>>;
+    let mut prev_discr = None::<Discr<'_>>;
 
     // fill the discriminant values and field types
     for variant in variants {
diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs
index 79a04b9..dd44f86 100644
--- a/src/librustc_typeck/constrained_generic_params.rs
+++ b/src/librustc_typeck/constrained_generic_params.rs
@@ -20,10 +20,10 @@
 }
 
 /// Returns the set of parameters constrained by the impl header.
-pub fn parameters_for_impl<'tcx>(impl_self_ty: Ty<'tcx>,
-                                 impl_trait_ref: Option<ty::TraitRef<'tcx>>)
-                                 -> FxHashSet<Parameter>
-{
+pub fn parameters_for_impl<'tcx>(
+    impl_self_ty: Ty<'tcx>,
+    impl_trait_ref: Option<ty::TraitRef<'tcx>>,
+) -> FxHashSet<Parameter> {
     let vec = match impl_trait_ref {
         Some(tr) => parameters_for(&tr, false),
         None => parameters_for(&impl_self_ty, false),
@@ -36,12 +36,10 @@
 /// uniquely determined by `t` (see RFC 447). If it is true, return the list
 /// of parameters whose values are needed in order to constrain `ty` - these
 /// differ, with the latter being a superset, in the presence of projections.
-pub fn parameters_for<'tcx, T>(t: &T,
-                               include_nonconstraining: bool)
-                               -> Vec<Parameter>
-    where T: TypeFoldable<'tcx>
-{
-
+pub fn parameters_for<'tcx>(
+    t: &impl TypeFoldable<'tcx>,
+    include_nonconstraining: bool,
+) -> Vec<Parameter> {
     let mut collector = ParameterCollector {
         parameters: vec![],
         include_nonconstraining,
diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs
index b52183d..e11dcfa 100644
--- a/src/librustc_typeck/error_codes.rs
+++ b/src/librustc_typeck/error_codes.rs
@@ -1,6 +1,6 @@
 // ignore-tidy-filelength
 
-register_long_diagnostics! {
+syntax::register_diagnostics! {
 
 E0023: r##"
 A pattern used to match against an enum variant must provide a sub-pattern for
@@ -212,7 +212,7 @@
 E0033: r##"
 This error indicates that a pointer to a trait type cannot be implicitly
 dereferenced by a pattern. Every trait defines a type, but because the
-size of trait implementors isn't fixed, this type has no compile-time size.
+size of trait implementers isn't fixed, this type has no compile-time size.
 Therefore, all accesses to trait types must be through pointers. If you
 encounter this error you should try to avoid dereferencing the pointer.
 
@@ -2425,6 +2425,87 @@
 ```
 "##,
 
+E0307: r##"
+This error indicates that the `self` parameter in a method has an invalid
+"reciever type".
+
+Methods take a special first parameter, of which there are three variants:
+`self`, `&self`, and `&mut self`. These are syntactic sugar for
+`self: Self`, `self: &Self`, and `self: &mut Self` respectively.
+
+```
+# struct Foo;
+trait Trait {
+    fn foo(&self);
+//         ^^^^^ `self` here is a reference to the receiver object
+}
+
+impl Trait for Foo {
+    fn foo(&self) {}
+//         ^^^^^ the receiver type is `&Foo`
+}
+```
+
+The type `Self` acts as an alias to the type of the current trait
+implementer, or "receiver type". Besides the already mentioned `Self`,
+`&Self` and `&mut Self` valid receiver types, the following are also valid:
+`self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, and `self: Pin<P>`
+(where P is one of the previous types except `Self`). Note that `Self` can
+also be the underlying implementing type, like `Foo` in the following
+example:
+
+```
+# struct Foo;
+# trait Trait {
+#     fn foo(&self);
+# }
+impl Trait for Foo {
+    fn foo(self: &Foo) {}
+}
+```
+
+E0307 will be emitted by the compiler when using an invalid reciver type,
+like in the following example:
+
+```compile_fail,E0307
+# struct Foo;
+# struct Bar;
+# trait Trait {
+#     fn foo(&self);
+# }
+impl Trait for Foo {
+    fn foo(self: &Bar) {}
+}
+```
+
+The nightly feature [Arbintrary self types][AST] extends the accepted
+set of receiver types to also include any type that can dereference to
+`Self`:
+
+```
+#![feature(arbitrary_self_types)]
+
+struct Foo;
+struct Bar;
+
+// Because you can dereference `Bar` into `Foo`...
+impl std::ops::Deref for Bar {
+    type Target = Foo;
+
+    fn deref(&self) -> &Foo {
+        &Foo
+    }
+}
+
+impl Foo {
+    fn foo(self: Bar) {}
+//         ^^^^^^^^^ ...it can be used as the receiver type
+}
+```
+
+[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html
+"##,
+
 E0321: r##"
 A cross-crate opt-out trait was implemented on something which wasn't a struct
 or enum type. Erroneous code example:
@@ -4789,10 +4870,7 @@
 The `Box<...>` ensures that the result is of known size,
 and the pin is required to keep it in the same place in memory.
 "##,
-
-}  // (end of detailed error messages)
-
-register_diagnostics! {
+;
 //  E0035, merged into E0087/E0089
 //  E0036, merged into E0087/E0089
 //  E0068,
@@ -4849,16 +4927,16 @@
 //  E0245, // not a trait
 //  E0246, // invalid recursive type
 //  E0247,
-//  E0248, // value used as a type, now reported earlier during resolution as E0412
+//  E0248, // value used as a type, now reported earlier during resolution
+           // as E0412
 //  E0249,
-    E0307, // invalid method `self` type
 //  E0319, // trait impls for defaulted traits allowed just for structs/enums
 //  E0372, // coherence not object safe
     E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with the same definition
 //  E0558, // replaced with a generic attribute input check
     E0533, // `{}` does not name a unit variant, unit struct or a constant
-//  E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
+//  E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
     E0564, // only named lifetimes are allowed in `impl Trait`,
            // but `{}` was found in the type `{}`
     E0587, // type has conflicting packed and align representation hints
@@ -4867,8 +4945,8 @@
 //  E0612, // merged into E0609
 //  E0613, // Removed (merged with E0609)
     E0627, // yield statement outside of generator literal
-    E0632, // cannot provide explicit type parameters when `impl Trait` is used in
-           // argument position.
+    E0632, // cannot provide explicit type parameters when `impl Trait` is used
+           // in argument position.
     E0634, // type has conflicting packed representaton hints
     E0640, // infer outlives requirements
     E0641, // cannot cast to/from a pointer with an unknown kind
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index fcfd9ad..bc0f17c 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -12,7 +12,7 @@
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::def_id::DefId;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc::ty::query::Providers;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -99,6 +99,15 @@
 ) {
     // Every lifetime used in an associated type must be constrained.
     let impl_self_ty = tcx.type_of(impl_def_id);
+    if impl_self_ty.references_error() {
+        // Don't complain about unconstrained type params when self ty isn't known due to errors.
+        // (#36836)
+        tcx.sess.delay_span_bug(
+            tcx.def_span(impl_def_id),
+            "potentially unconstrained type parameters weren't evaluated",
+        );
+        return;
+    }
     let impl_generics = tcx.generics_of(impl_def_id);
     let impl_predicates = tcx.predicates_of(impl_def_id);
     let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 9d9a9d9..959483e 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -65,7 +65,6 @@
 #![feature(exhaustive_patterns)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(never_type)]
 #![feature(inner_deref)]
@@ -78,9 +77,7 @@
 
 #[macro_use] extern crate rustc;
 
-// N.B., this module needs to be declared first so diagnostics are
-// registered before they are used.
-mod error_codes;
+pub mod error_codes;
 
 mod astconv;
 mod check;
@@ -389,5 +386,3 @@
 
     bounds
 }
-
-__build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }
diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs
index 3e3eab8..273a36e 100644
--- a/src/librustc_typeck/structured_errors.rs
+++ b/src/librustc_typeck/structured_errors.rs
@@ -48,7 +48,7 @@
     fn session(&self) -> &Session { self.sess }
 
     fn code(&self) -> DiagnosticId {
-        __diagnostic_used!(E0617);
+        syntax::diagnostic_used!(E0617);
         DiagnosticId::Error("E0617".to_owned())
     }
 
@@ -104,7 +104,7 @@
     fn session(&self) -> &Session { self.sess }
 
     fn code(&self) -> DiagnosticId {
-        __diagnostic_used!(E0607);
+        syntax::diagnostic_used!(E0607);
         DiagnosticId::Error("E0607".to_owned())
     }
 
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index b9b3e62..c3092ce 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -81,10 +81,10 @@
             },
             MetaItemKind::List(ref items) => {
                 let mut sub_cfgs = items.iter().map(Cfg::parse_nested);
-                match &*name.as_str() {
-                    "all" => sub_cfgs.fold(Ok(Cfg::True), |x, y| Ok(x? & y?)),
-                    "any" => sub_cfgs.fold(Ok(Cfg::False), |x, y| Ok(x? | y?)),
-                    "not" => if sub_cfgs.len() == 1 {
+                match name {
+                    sym::all => sub_cfgs.fold(Ok(Cfg::True), |x, y| Ok(x? & y?)),
+                    sym::any => sub_cfgs.fold(Ok(Cfg::False), |x, y| Ok(x? | y?)),
+                    sym::not => if sub_cfgs.len() == 1 {
                         Ok(!sub_cfgs.next().unwrap()?)
                     } else {
                         Err(InvalidCfgError {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 4971155..ae70fdc 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1039,7 +1039,7 @@
     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).as_str(),
+        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 {
@@ -1138,13 +1138,13 @@
 
 // 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: &str, trait_did: Option<DefId>, has_self: bool,
+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(),
+            name: name.as_str().to_string(),
             args: external_generic_args(cx, trait_did, has_self, bindings, substs)
         }],
     }
@@ -1154,7 +1154,7 @@
     fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
         let (trait_ref, ref bounds) = *self;
         inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
-        let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(),
+        let path = external_path(cx, cx.tcx.item_name(trait_ref.def_id),
                                  Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
 
         debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
@@ -3089,8 +3089,7 @@
                     AdtKind::Enum => TypeKind::Enum,
                 };
                 inline::record_extern_fqn(cx, did, kind);
-                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
-                                         None, false, vec![], substs);
+                let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
                 ResolvedPath {
                     path,
                     param_names: None,
@@ -3100,7 +3099,7 @@
             }
             ty::Foreign(did) => {
                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
-                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
+                let path = external_path(cx, cx.tcx.item_name(did),
                                          None, false, vec![], InternalSubsts::empty());
                 ResolvedPath {
                     path: path,
@@ -3129,7 +3128,7 @@
                 reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
                 for did in dids {
                     let empty = cx.tcx.intern_substs(&[]);
-                    let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
+                    let path = external_path(cx, cx.tcx.item_name(did),
                         Some(did), false, vec![], empty);
                     inline::record_extern_fqn(cx, did, TypeKind::Trait);
                     let bound = GenericBound::TraitBound(PolyTrait {
@@ -3154,7 +3153,7 @@
                     });
                 }
 
-                let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
+                let path = external_path(cx, cx.tcx.item_name(did), Some(did),
                     false, bindings, substs);
                 ResolvedPath {
                     path,
@@ -3977,7 +3976,7 @@
             F32 => tcx.lang_items().f32_impl(),
             F64 => tcx.lang_items().f64_impl(),
             Char => tcx.lang_items().char_impl(),
-            Bool => None,
+            Bool => tcx.lang_items().bool_impl(),
             Str => tcx.lang_items().str_impl(),
             Slice => tcx.lang_items().slice_impl(),
             Array => tcx.lang_items().slice_impl(),
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 30b1706..19ea781 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -9,7 +9,7 @@
 use rustc::session::config::{CrateType, parse_crate_types_from_list};
 use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
 use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options,
-                             get_cmd_lint_options, ExternEntry};
+                             get_cmd_lint_options, host_triple, ExternEntry};
 use rustc::session::search_paths::SearchPath;
 use rustc_driver;
 use rustc_target::spec::TargetTriple;
@@ -54,14 +54,12 @@
     /// Debugging (`-Z`) options to pass to the compiler.
     pub debugging_options: DebuggingOptions,
     /// The target used to compile the crate against.
-    pub target: Option<TargetTriple>,
+    pub target: TargetTriple,
     /// Edition used when reading the crate. Defaults to "2015". Also used by default when
     /// compiling doctests from the crate.
     pub edition: Edition,
     /// The path to the sysroot. Used during the compilation process.
     pub maybe_sysroot: Option<PathBuf>,
-    /// Linker to use when building doctests.
-    pub linker: Option<PathBuf>,
     /// Lint information passed over the command-line.
     pub lint_opts: Vec<(String, Level)>,
     /// Whether to ask rustc to describe the lints it knows. Practically speaking, this will not be
@@ -79,6 +77,18 @@
     /// Optional path to persist the doctest executables to, defaults to a
     /// temporary directory if not set.
     pub persist_doctests: Option<PathBuf>,
+    /// Runtool to run doctests with
+    pub runtool: Option<String>,
+    /// Arguments to pass to the runtool
+    pub runtool_args: Vec<String>,
+    /// Whether to allow ignoring doctests on a per-target basis
+    /// For example, using ignore-foo to ignore running the doctest on any target that
+    /// contains "foo" as a substring
+    pub enable_per_target_ignores: bool,
+
+    /// The path to a rustc-like binary to build tests with. If not set, we
+    /// default to loading from $sysroot/bin/rustc.
+    pub test_builder: Option<PathBuf>,
 
     // Options that affect the documentation process
 
@@ -130,7 +140,6 @@
             .field("target", &self.target)
             .field("edition", &self.edition)
             .field("maybe_sysroot", &self.maybe_sysroot)
-            .field("linker", &self.linker)
             .field("lint_opts", &self.lint_opts)
             .field("describe_lints", &self.describe_lints)
             .field("lint_cap", &self.lint_cap)
@@ -143,6 +152,9 @@
             .field("show_coverage", &self.show_coverage)
             .field("crate_version", &self.crate_version)
             .field("render_options", &self.render_options)
+            .field("runtool", &self.runtool)
+            .field("runtool_args", &self.runtool_args)
+            .field("enable-per-target-ignores", &self.enable_per_target_ignores)
             .finish()
     }
 }
@@ -417,7 +429,9 @@
             }
         }
 
-        let target = matches.opt_str("target").map(|target| {
+        let target = matches.opt_str("target").map_or(
+            TargetTriple::from_triple(host_triple()),
+            |target| {
             if target.ends_with(".json") {
                 TargetTriple::TargetPath(PathBuf::from(target))
             } else {
@@ -454,7 +468,6 @@
         let playground_url = matches.opt_str("playground-url");
         let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
         let display_warnings = matches.opt_present("display-warnings");
-        let linker = matches.opt_str("linker").map(PathBuf::from);
         let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
         let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
         let enable_minification = !matches.opt_present("disable-minification");
@@ -467,9 +480,13 @@
         let generate_search_filter = !matches.opt_present("disable-per-crate-search");
         let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from);
         let generate_redirect_pages = matches.opt_present("generate-redirect-pages");
+        let test_builder = matches.opt_str("test-builder").map(PathBuf::from);
         let codegen_options_strs = matches.opt_strs("C");
         let lib_strs = matches.opt_strs("L");
         let extern_strs = matches.opt_strs("extern");
+        let runtool = matches.opt_str("runtool");
+        let runtool_args = matches.opt_strs("runtool-arg");
+        let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores");
 
         let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
@@ -489,7 +506,6 @@
             target,
             edition,
             maybe_sysroot,
-            linker,
             lint_opts,
             describe_lints,
             lint_cap,
@@ -501,6 +517,10 @@
             show_coverage,
             crate_version,
             persist_doctests,
+            runtool,
+            runtool_args,
+            enable_per_target_ignores,
+            test_builder,
             render_options: RenderOptions {
                 output,
                 external_html,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 9cfcad4..57b016a 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -13,7 +13,6 @@
 use rustc_driver::abort_on_err;
 use rustc_resolve as resolve;
 use rustc_metadata::cstore::CStore;
-use rustc_target::spec::TargetTriple;
 
 use syntax::source_map;
 use syntax::attr;
@@ -294,7 +293,6 @@
         }
     }).collect();
 
-    let host_triple = TargetTriple::from_triple(config::host_triple());
     let crate_types = if proc_macro_crate {
         vec![config::CrateType::ProcMacro]
     } else {
@@ -313,7 +311,7 @@
         lint_cap: Some(lint_cap.unwrap_or_else(|| lint::Forbid)),
         cg: codegen_options,
         externs,
-        target_triple: target.unwrap_or(host_triple),
+        target_triple: target,
         // Ensure that rustdoc works even if rustc is feature-staged
         unstable_features: UnstableFeatures::Allow,
         actually_rustdoc: true,
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 313734e..dcd3219 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -18,6 +18,100 @@
 use crate::html::item_type::ItemType;
 use crate::html::render::{self, cache, CURRENT_DEPTH};
 
+pub trait Print {
+    fn print(self, buffer: &mut Buffer);
+}
+
+impl<F> Print for F
+    where F: FnOnce(&mut Buffer),
+{
+    fn print(self, buffer: &mut Buffer) {
+        (self)(buffer)
+    }
+}
+
+impl Print for String {
+    fn print(self, buffer: &mut Buffer) {
+        buffer.write_str(&self);
+    }
+}
+
+impl Print for &'_ str {
+    fn print(self, buffer: &mut Buffer) {
+        buffer.write_str(self);
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct Buffer {
+    for_html: bool,
+    buffer: String,
+}
+
+impl Buffer {
+    crate fn empty_from(v: &Buffer) -> Buffer {
+        Buffer {
+            for_html: v.for_html,
+            buffer: String::new(),
+        }
+    }
+
+    crate fn html() -> Buffer {
+        Buffer {
+            for_html: true,
+            buffer: String::new(),
+        }
+    }
+
+    crate fn is_empty(&self) -> bool {
+        self.buffer.is_empty()
+    }
+
+    crate fn into_inner(self) -> String {
+        self.buffer
+    }
+
+    crate fn insert_str(&mut self, idx: usize, s: &str) {
+        self.buffer.insert_str(idx, s);
+    }
+
+    crate fn push_str(&mut self, s: &str) {
+        self.buffer.push_str(s);
+    }
+
+    // Intended for consumption by write! and writeln! (std::fmt) but without
+    // the fmt::Result return type imposed by fmt::Write (and avoiding the trait
+    // import).
+    crate fn write_str(&mut self, s: &str) {
+        self.buffer.push_str(s);
+    }
+
+    // Intended for consumption by write! and writeln! (std::fmt) but without
+    // the fmt::Result return type imposed by fmt::Write (and avoiding the trait
+    // import).
+    crate fn write_fmt(&mut self, v: fmt::Arguments<'_>) {
+        use fmt::Write;
+        self.buffer.write_fmt(v).unwrap();
+    }
+
+    crate fn to_display<T: Print>(mut self, t: T) -> String {
+        t.print(&mut self);
+        self.into_inner()
+    }
+
+    crate fn with_formatter<T: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result>(&mut self, t: T) {
+        self.from_display(display_fn(move |f| (t)(f)));
+    }
+
+    crate fn from_display<T: std::fmt::Display>(&mut self, t: T) {
+        if self.for_html {
+            write!(self, "{}", t);
+        } else {
+            write!(self, "{:#}", t);
+        }
+    }
+}
+
 /// Helper to render an optional visibility with a space after it (if the
 /// visibility is preset)
 #[derive(Copy, Clone)]
@@ -200,11 +294,11 @@
                 }
                 &clean::WherePredicate::RegionPredicate { ref lifetime, ref bounds } => {
                     clause.push_str(&format!("{}: {}",
-                                             lifetime,
-                                             bounds.iter()
-                                                   .map(|b| b.to_string())
-                                                   .collect::<Vec<_>>()
-                                                   .join(" + ")));
+                                                lifetime,
+                                                bounds.iter()
+                                                    .map(|b| b.to_string())
+                                                    .collect::<Vec<_>>()
+                                                    .join(" + ")));
                 }
                 &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
                     if f.alternate() {
@@ -778,9 +872,9 @@
 
 // The difference from above is that trait is not hyperlinked.
 pub fn fmt_impl_for_trait_page(i: &clean::Impl,
-                               f: &mut fmt::Formatter<'_>,
-                               use_absolute: bool) -> fmt::Result {
-    fmt_impl(i, f, false, use_absolute)
+                               f: &mut Buffer,
+                               use_absolute: bool) {
+    f.with_formatter(|f| fmt_impl(i, f, false, use_absolute))
 }
 
 impl fmt::Display for clean::Arguments {
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index ae0bd1a..56074f4 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -1,9 +1,8 @@
-use std::fmt;
-use std::io;
 use std::path::PathBuf;
 
 use crate::externalfiles::ExternalHtml;
 use crate::html::render::SlashChecker;
+use crate::html::format::{Buffer, Print};
 
 #[derive(Clone)]
 pub struct Layout {
@@ -11,6 +10,12 @@
     pub favicon: String,
     pub external_html: ExternalHtml,
     pub krate: String,
+    /// The given user css file which allow to customize the generated
+    /// documentation theme.
+    pub css_file_extension: Option<PathBuf>,
+    /// If false, the `select` element to have search filtering by crates on rendered docs
+    /// won't be generated.
+    pub generate_search_filter: bool,
 }
 
 pub struct Page<'a> {
@@ -25,19 +30,15 @@
     pub static_extra_scripts: &'a [&'a str],
 }
 
-pub fn render<T: fmt::Display, S: fmt::Display>(
-    dst: &mut dyn io::Write,
+pub fn render<T: Print, S: Print>(
     layout: &Layout,
     page: &Page<'_>,
-    sidebar: &S,
-    t: &T,
-    css_file_extension: bool,
+    sidebar: S,
+    t: T,
     themes: &[PathBuf],
-    generate_search_filter: bool,
-) -> io::Result<()> {
+) -> String {
     let static_root_path = page.static_root_path.unwrap_or(page.root_path);
-    write!(dst,
-"<!DOCTYPE html>\
+    format!("<!DOCTYPE html>\
 <html lang=\"en\">\
 <head>\
     <meta charset=\"utf-8\">\
@@ -164,7 +165,7 @@
     <script defer src=\"{root_path}search-index{suffix}.js\"></script>\
 </body>\
 </html>",
-    css_extension = if css_file_extension {
+    css_extension = if layout.css_file_extension.is_some() {
         format!("<link rel=\"stylesheet\" \
                        type=\"text/css\" \
                        href=\"{static_root_path}theme{suffix}.css\">",
@@ -173,7 +174,7 @@
     } else {
         String::new()
     },
-    content   = *t,
+    content   = Buffer::html().to_display(t),
     static_root_path = static_root_path,
     root_path = page.root_path,
     css_class = page.css_class,
@@ -207,7 +208,7 @@
     in_header = layout.external_html.in_header,
     before_content = layout.external_html.before_content,
     after_content = layout.external_html.after_content,
-    sidebar   = *sidebar,
+    sidebar   = Buffer::html().to_display(sidebar),
     krate     = layout.krate,
     themes = themes.iter()
                    .filter_map(|t| t.file_stem())
@@ -228,7 +229,7 @@
                 root_path=page.root_path,
                 extra_script=e)
     }).collect::<String>(),
-    filter_crates=if generate_search_filter {
+    filter_crates=if layout.generate_search_filter {
         "<select id=\"crate-search\">\
             <option value=\"All crates\">All crates</option>\
         </select>"
@@ -238,9 +239,9 @@
     )
 }
 
-pub fn redirect(dst: &mut dyn io::Write, url: &str) -> io::Result<()> {
+pub fn redirect(url: &str) -> String {
     // <script> triggers a redirect before refresh, so this is fine.
-    write!(dst,
+    format!(
 r##"<!DOCTYPE html>
 <html lang="en">
 <head>
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 74413a7..1a4fa38 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -199,7 +199,7 @@
         let ignore;
         let edition;
         if let Some(Event::Start(Tag::CodeBlock(lang))) = event {
-            let parse_result = LangString::parse(&lang, self.check_error_codes);
+            let parse_result = LangString::parse(&lang, self.check_error_codes, false);
             if !parse_result.rust {
                 return Some(Event::Start(Tag::CodeBlock(lang)));
             }
@@ -272,7 +272,7 @@
             ))
         });
 
-        let tooltip = if ignore {
+        let tooltip = if ignore != Ignore::None {
             Some(("This example is not tested".to_owned(), "ignore"))
         } else if compile_fail {
             Some(("This example deliberately fails to compile".to_owned(), "compile_fail"))
@@ -286,7 +286,7 @@
             s.push_str(&highlight::render_with_highlighting(
                 &text,
                 Some(&format!("rust-example-rendered{}",
-                                if ignore { " ignore" }
+                                if ignore != Ignore::None { " ignore" }
                                 else if compile_fail { " compile_fail" }
                                 else if explicit_edition { " edition " }
                                 else { "" })),
@@ -297,7 +297,7 @@
             s.push_str(&highlight::render_with_highlighting(
                 &text,
                 Some(&format!("rust-example-rendered{}",
-                                if ignore { " ignore" }
+                                if ignore != Ignore::None { " ignore" }
                                 else if compile_fail { " compile_fail" }
                                 else if explicit_edition { " edition " }
                                 else { "" })),
@@ -551,7 +551,8 @@
     }
 }
 
-pub fn find_testable_code<T: test::Tester>(doc: &str, tests: &mut T, error_codes: ErrorCodes) {
+pub fn find_testable_code<T: test::Tester>(doc: &str, tests: &mut T, error_codes: ErrorCodes,
+                                           enable_per_target_ignores: bool) {
     let mut parser = Parser::new(doc);
     let mut prev_offset = 0;
     let mut nb_lines = 0;
@@ -564,7 +565,7 @@
                 let block_info = if s.is_empty() {
                     LangString::all_false()
                 } else {
-                    LangString::parse(&*s, error_codes)
+                    LangString::parse(&*s, error_codes, enable_per_target_ignores)
                 };
                 if !block_info.rust {
                     continue;
@@ -607,7 +608,7 @@
     original: String,
     pub should_panic: bool,
     pub no_run: bool,
-    pub ignore: bool,
+    pub ignore: Ignore,
     pub rust: bool,
     pub test_harness: bool,
     pub compile_fail: bool,
@@ -616,13 +617,20 @@
     pub edition: Option<Edition>
 }
 
+#[derive(Eq, PartialEq, Clone, Debug)]
+pub enum Ignore {
+    All,
+    None,
+    Some(Vec<String>),
+}
+
 impl LangString {
     fn all_false() -> LangString {
         LangString {
             original: String::new(),
             should_panic: false,
             no_run: false,
-            ignore: false,
+            ignore: Ignore::None,
             rust: true,  // NB This used to be `notrust = false`
             test_harness: false,
             compile_fail: false,
@@ -632,11 +640,16 @@
         }
     }
 
-    fn parse(string: &str, allow_error_code_check: ErrorCodes) -> LangString {
+    fn parse(
+        string: &str,
+        allow_error_code_check: ErrorCodes,
+        enable_per_target_ignores: bool
+    ) -> LangString {
         let allow_error_code_check = allow_error_code_check.as_bool();
         let mut seen_rust_tags = false;
         let mut seen_other_tags = false;
         let mut data = LangString::all_false();
+        let mut ignores = vec![];
 
         data.original = string.to_owned();
         let tokens = string.split(|c: char|
@@ -651,7 +664,11 @@
                     seen_rust_tags = seen_other_tags == false;
                 }
                 "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
-                "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
+                "ignore" => { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; }
+                x if x.starts_with("ignore-") => if enable_per_target_ignores {
+                    ignores.push(x.trim_start_matches("ignore-").to_owned());
+                    seen_rust_tags = !seen_other_tags;
+                }
                 "allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; }
                 "rust" => { data.rust = true; seen_rust_tags = true; }
                 "test_harness" => {
@@ -679,6 +696,10 @@
                 _ => { seen_other_tags = true }
             }
         }
+        // ignore-foo overrides ignore
+        if !ignores.is_empty() {
+            data.ignore = Ignore::Some(ignores);
+        }
 
         data.rust &= !seen_other_tags || seen_rust_tags;
 
@@ -919,7 +940,7 @@
                 let lang_string = if syntax.is_empty() {
                     LangString::all_false()
                 } else {
-                    LangString::parse(&*syntax, ErrorCodes::Yes)
+                    LangString::parse(&*syntax, ErrorCodes::Yes, false)
                 };
 
                 if lang_string.rust {
@@ -931,7 +952,10 @@
                             is_fenced = true;
                             previous_offset + fence_idx
                         }
-                        None => offset,
+                        None => {
+                            is_fenced = false;
+                            offset
+                        }
                     };
                 }
             }
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index a95c290..5d6811a 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -1,4 +1,4 @@
-use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap};
+use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap, Ignore};
 use super::plain_summary_line;
 use std::cell::RefCell;
 use syntax::edition::{Edition, DEFAULT_EDITION};
@@ -26,10 +26,10 @@
 #[test]
 fn test_lang_string_parse() {
     fn t(s: &str,
-        should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
+        should_panic: bool, no_run: bool, ignore: Ignore, rust: bool, test_harness: bool,
         compile_fail: bool, allow_fail: bool, error_codes: Vec<String>,
-         edition: Option<Edition>) {
-        assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString {
+        edition: Option<Edition>) {
+        assert_eq!(LangString::parse(s, ErrorCodes::Yes, true), LangString {
             should_panic,
             no_run,
             ignore,
@@ -42,6 +42,7 @@
             edition,
         })
     }
+    let ignore_foo = Ignore::Some(vec!("foo".to_string()));
 
     fn v() -> Vec<String> {
         Vec::new()
@@ -50,23 +51,24 @@
     // ignore-tidy-linelength
     // marker                | should_panic | no_run | ignore | rust | test_harness
     //                       | compile_fail | allow_fail | error_codes | edition
-    t("",                      false,         false,   false,   true,  false, false, false, v(), None);
-    t("rust",                  false,         false,   false,   true,  false, false, false, v(), None);
-    t("sh",                    false,         false,   false,   false, false, false, false, v(), None);
-    t("ignore",                false,         false,   true,    true,  false, false, false, v(), None);
-    t("should_panic",          true,          false,   false,   true,  false, false, false, v(), None);
-    t("no_run",                false,         true,    false,   true,  false, false, false, v(), None);
-    t("test_harness",          false,         false,   false,   true,  true,  false, false, v(), None);
-    t("compile_fail",          false,         true,    false,   true,  false, true,  false, v(), None);
-    t("allow_fail",            false,         false,   false,   true,  false, false, true,  v(), None);
-    t("{.no_run .example}",    false,         true,    false,   true,  false, false, false, v(), None);
-    t("{.sh .should_panic}",   true,          false,   false,   false, false, false, false, v(), None);
-    t("{.example .rust}",      false,         false,   false,   true,  false, false, false, v(), None);
-    t("{.test_harness .rust}", false,         false,   false,   true,  true,  false, false, v(), None);
-    t("text, no_run",          false,         true,    false,   false, false, false, false, v(), None);
-    t("text,no_run",           false,         true,    false,   false, false, false, false, v(), None);
-    t("edition2015",           false,         false,   false,   true,  false, false, false, v(), Some(Edition::Edition2015));
-    t("edition2018",           false,         false,   false,   true,  false, false, false, v(), Some(Edition::Edition2018));
+    t("",                      false,         false,   Ignore::None,   true,  false, false, false, v(), None);
+    t("rust",                  false,         false,   Ignore::None,   true,  false, false, false, v(), None);
+    t("sh",                    false,         false,   Ignore::None,   false, false, false, false, v(), None);
+    t("ignore",                false,         false,   Ignore::All,    true,  false, false, false, v(), None);
+    t("ignore-foo",            false,         false,   ignore_foo,     true,  false, false, false, v(), None);
+    t("should_panic",          true,          false,   Ignore::None,   true,  false, false, false, v(), None);
+    t("no_run",                false,         true,    Ignore::None,   true,  false, false, false, v(), None);
+    t("test_harness",          false,         false,   Ignore::None,   true,  true,  false, false, v(), None);
+    t("compile_fail",          false,         true,    Ignore::None,   true,  false, true,  false, v(), None);
+    t("allow_fail",            false,         false,   Ignore::None,   true,  false, false, true,  v(), None);
+    t("{.no_run .example}",    false,         true,    Ignore::None,   true,  false, false, false, v(), None);
+    t("{.sh .should_panic}",   true,          false,   Ignore::None,   false, false, false, false, v(), None);
+    t("{.example .rust}",      false,         false,   Ignore::None,   true,  false, false, false, v(), None);
+    t("{.test_harness .rust}", false,         false,   Ignore::None,   true,  true,  false, false, v(), None);
+    t("text, no_run",          false,         true,    Ignore::None,   false, false, false, false, v(), None);
+    t("text,no_run",           false,         true,    Ignore::None,   false, false, false, false, v(), None);
+    t("edition2015",           false,         false,   Ignore::None,   true,  false, false, false, v(), Some(Edition::Edition2015));
+    t("edition2018",           false,         false,   Ignore::None,   true,  false, false, false, v(), Some(Edition::Edition2018));
 }
 
 #[test]
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index d5c47a1..9846073 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -65,7 +65,7 @@
 use crate::doctree;
 use crate::fold::DocFolder;
 use crate::html::escape::Escape;
-use crate::html::format::{AsyncSpace, ConstnessSpace};
+use crate::html::format::{Buffer, AsyncSpace, ConstnessSpace};
 use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace};
 use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace};
 use crate::html::format::fmt_impl_for_trait_page;
@@ -192,9 +192,6 @@
     /// The base-URL of the issue tracker for when an item has been tagged with
     /// an issue number.
     pub issue_tracker_base_url: Option<String>,
-    /// The given user css file which allow to customize the generated
-    /// documentation theme.
-    pub css_file_extension: Option<PathBuf>,
     /// The directories that have already been created in this doc run. Used to reduce the number
     /// of spurious `create_dir_all` calls.
     pub created_dirs: RefCell<FxHashSet<PathBuf>>,
@@ -209,9 +206,6 @@
     /// Optional path string to be used to load static files on output pages. If not set, uses
     /// combinations of `../` to reach the documentation root.
     pub static_root_path: Option<String>,
-    /// If false, the `select` element to have search filtering by crates on rendered docs
-    /// won't be generated.
-    pub generate_search_filter: bool,
     /// Option disabled by default to generate files used by RLS and some other tools.
     pub generate_redirect_pages: bool,
     /// The fs handle we are working with.
@@ -387,14 +381,6 @@
 // Helper structs for rendering items/sidebars and carrying along contextual
 // information
 
-#[derive(Copy, Clone)]
-struct Item<'a> {
-    cx: &'a Context,
-    item: &'a clean::Item,
-}
-
-struct Sidebar<'a> { cx: &'a Context, item: &'a clean::Item, }
-
 /// Struct representing one entry in the JS search index. These are all emitted
 /// by hand to a large JS file at the end of cache-creation.
 #[derive(Debug)]
@@ -545,14 +531,14 @@
             favicon: String::new(),
             external_html,
             krate: krate.name.clone(),
+            css_file_extension: extension_css,
+            generate_search_filter,
         },
-        css_file_extension: extension_css,
         created_dirs: Default::default(),
         sort_modules_alphabetically,
         themes,
         resource_suffix,
         static_root_path,
-        generate_search_filter,
         generate_redirect_pages,
         fs: DocFS::new(&errors),
     };
@@ -932,7 +918,7 @@
             options.enable_minification)?;
     }
 
-    if let Some(ref css) = cx.shared.css_file_extension {
+    if let Some(ref css) = cx.shared.layout.css_file_extension {
         let out = cx.dst.join(&format!("theme{}.css", cx.shared.resource_suffix));
         let buffer = try_err!(fs::read_to_string(css), css);
         if !options.enable_minification {
@@ -1031,12 +1017,12 @@
         }
         all_aliases.push(format!("ALIASES[\"{}\"] = {{{}}};", krate.name, output));
         all_aliases.sort();
-        let mut v = Vec::new();
-        try_err!(writeln!(&mut v, "var ALIASES = {{}};"), &dst);
+        let mut v = Buffer::html();
+        writeln!(&mut v, "var ALIASES = {{}};");
         for aliases in &all_aliases {
-            try_err!(writeln!(&mut v, "{}", aliases), &dst);
+            writeln!(&mut v, "{}", aliases);
         }
-        cx.shared.fs.write(&dst, &v)?;
+        cx.shared.fs.write(&dst, v.into_inner().into_bytes())?;
     }
 
     use std::ffi::OsString;
@@ -1120,12 +1106,9 @@
                                  &krate.name,
                                  hierarchy.to_json_string()));
         all_sources.sort();
-        let mut v = Vec::new();
-        try_err!(writeln!(&mut v,
-                          "var N = null;var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();",
-                          all_sources.join("\n")),
-                 &dst);
-        cx.shared.fs.write(&dst, &v)?;
+        let v = format!("var N = null;var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();\n",
+                          all_sources.join("\n"));
+        cx.shared.fs.write(&dst, v.as_bytes())?;
     }
 
     // Update the search index
@@ -1140,14 +1123,11 @@
     // with rustdoc running in parallel.
     all_indexes.sort();
     {
-        let mut v = Vec::new();
-        try_err!(writeln!(&mut v, "var N=null,E=\"\",T=\"t\",U=\"u\",searchIndex={{}};"), &dst);
-        try_err!(write_minify_replacer(
-            &mut v,
+        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),
-            &dst);
-        try_err!(write!(&mut v, "initSearch(searchIndex);addSearchOptions(searchIndex);"), &dst);
+            options.enable_minification));
+        v.push_str("initSearch(searchIndex);addSearchOptions(searchIndex);");
         cx.shared.fs.write(&dst, &v)?;
     }
     if options.enable_index_page {
@@ -1185,13 +1165,10 @@
                                                 SlashChecker(s), s)
                                     })
                                     .collect::<String>());
-            let mut v = Vec::new();
-            try_err!(layout::render(&mut v, &cx.shared.layout,
-                                    &page, &(""), &content,
-                                    cx.shared.css_file_extension.is_some(),
-                                    &cx.shared.themes,
-                                    cx.shared.generate_search_filter), &dst);
-            cx.shared.fs.write(&dst, &v)?;
+            let v = layout::render(&cx.shared.layout,
+                           &page, "", content,
+                           &cx.shared.themes);
+            cx.shared.fs.write(&dst, v.as_bytes())?;
         }
     }
 
@@ -1256,19 +1233,18 @@
         // identically even with rustdoc running in parallel.
         all_implementors.sort();
 
-        let mut v = Vec::new();
-        try_err!(writeln!(&mut v, "(function() {{var implementors = {{}};"), &mydst);
+        let mut v = String::from("(function() {var implementors = {};\n");
         for implementor in &all_implementors {
-            try_err!(writeln!(&mut v, "{}", *implementor), &mydst);
+            writeln!(v, "{}", *implementor).unwrap();
         }
-        try_err!(writeln!(&mut v, "{}", r"
+        v.push_str(r"
             if (window.register_implementors) {
                 window.register_implementors(implementors);
             } else {
                 window.pending_implementors = implementors;
             }
-        "), &mydst);
-        try_err!(writeln!(&mut v, r"}})()"), &mydst);
+        ");
+        v.push_str("})()");
         cx.shared.fs.write(&mydst, &v)?;
     }
     Ok(())
@@ -1288,68 +1264,65 @@
     }
 }
 
-fn write_minify_replacer<W: Write>(
-    dst: &mut W,
+fn minify_replacer(
     contents: &str,
     enable_minification: bool,
-) -> io::Result<()> {
+) -> String {
     use minifier::js::{simple_minify, Keyword, ReservedChar, Token, Tokens};
 
     if enable_minification {
-        writeln!(dst, "{}",
-                 {
-                    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();
-                    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()
+        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 {
-        writeln!(dst, "{}", contents)
+        format!("{}\n", contents)
     }
 }
 
@@ -1778,8 +1751,7 @@
     }
 }
 
-fn print_entries(f: &mut fmt::Formatter<'_>, e: &FxHashSet<ItemEntry>, title: &str,
-                 class: &str) -> fmt::Result {
+fn print_entries(f: &mut Buffer, e: &FxHashSet<ItemEntry>, title: &str, class: &str) {
     if !e.is_empty() {
         let mut e: Vec<&ItemEntry> = e.iter().collect();
         e.sort();
@@ -1787,90 +1759,71 @@
                title,
                Escape(title),
                class,
-               e.iter().map(|s| format!("<li>{}</li>", s)).collect::<String>())?;
+               e.iter().map(|s| format!("<li>{}</li>", s)).collect::<String>());
     }
-    Ok(())
 }
 
-impl fmt::Display for AllTypes {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl AllTypes {
+    fn print(self, f: &mut Buffer) {
         write!(f,
-"<h1 class='fqn'>\
-     <span class='out-of-band'>\
-         <span id='render-detail'>\
-             <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" title=\"collapse all docs\">\
-                 [<span class='inner'>&#x2212;</span>]\
-             </a>\
-         </span>
-     </span>
-     <span class='in-band'>List of all items</span>\
-</h1>")?;
-        print_entries(f, &self.structs, "Structs", "structs")?;
-        print_entries(f, &self.enums, "Enums", "enums")?;
-        print_entries(f, &self.unions, "Unions", "unions")?;
-        print_entries(f, &self.primitives, "Primitives", "primitives")?;
-        print_entries(f, &self.traits, "Traits", "traits")?;
-        print_entries(f, &self.macros, "Macros", "macros")?;
-        print_entries(f, &self.attributes, "Attribute Macros", "attributes")?;
-        print_entries(f, &self.derives, "Derive Macros", "derives")?;
-        print_entries(f, &self.functions, "Functions", "functions")?;
-        print_entries(f, &self.typedefs, "Typedefs", "typedefs")?;
-        print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases")?;
-        print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types")?;
-        print_entries(f, &self.statics, "Statics", "statics")?;
+    "<h1 class='fqn'>\
+        <span class='out-of-band'>\
+            <span id='render-detail'>\
+                <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" title=\"collapse all docs\">\
+                    [<span class='inner'>&#x2212;</span>]\
+                </a>\
+            </span>
+        </span>
+        <span class='in-band'>List of all items</span>\
+    </h1>");
+        print_entries(f, &self.structs, "Structs", "structs");
+        print_entries(f, &self.enums, "Enums", "enums");
+        print_entries(f, &self.unions, "Unions", "unions");
+        print_entries(f, &self.primitives, "Primitives", "primitives");
+        print_entries(f, &self.traits, "Traits", "traits");
+        print_entries(f, &self.macros, "Macros", "macros");
+        print_entries(f, &self.attributes, "Attribute Macros", "attributes");
+        print_entries(f, &self.derives, "Derive Macros", "derives");
+        print_entries(f, &self.functions, "Functions", "functions");
+        print_entries(f, &self.typedefs, "Typedefs", "typedefs");
+        print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases");
+        print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types");
+        print_entries(f, &self.statics, "Statics", "statics");
         print_entries(f, &self.constants, "Constants", "constants")
     }
 }
 
-#[derive(Debug)]
-struct Settings<'a> {
+fn settings(root_path: &str, suffix: &str) -> String {
     // (id, explanation, default value)
-    settings: Vec<(&'static str, &'static str, bool)>,
-    root_path: &'a str,
-    suffix: &'a str,
-}
-
-impl<'a> Settings<'a> {
-    pub fn new(root_path: &'a str, suffix: &'a str) -> Settings<'a> {
-        Settings {
-            settings: vec![
-                ("item-declarations", "Auto-hide item declarations.", true),
-                ("item-attributes", "Auto-hide item attributes.", true),
-                ("trait-implementations", "Auto-hide trait implementations documentation",
-                 true),
-                ("method-docs", "Auto-hide item methods' documentation", false),
-                ("go-to-only-result", "Directly go to item in search if there is only one result",
-                 false),
-                ("line-numbers", "Show line numbers on code examples", false),
-            ],
-            root_path,
-            suffix,
-        }
-    }
-}
-
-impl<'a> fmt::Display for Settings<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f,
+    let settings = [
+        ("item-declarations", "Auto-hide item declarations.", true),
+        ("item-attributes", "Auto-hide item attributes.", true),
+        ("trait-implementations", "Auto-hide trait implementations documentation",
+            true),
+        ("method-docs", "Auto-hide item methods' documentation", false),
+        ("go-to-only-result", "Directly go to item in search if there is only one result",
+            false),
+        ("line-numbers", "Show line numbers on code examples", false),
+    ];
+    format!(
 "<h1 class='fqn'>\
-     <span class='in-band'>Rustdoc settings</span>\
+    <span class='in-band'>Rustdoc settings</span>\
 </h1>\
 <div class='settings'>{}</div>\
 <script src='{}settings{}.js'></script>",
-               self.settings.iter()
-                            .map(|(id, text, enabled)| {
-                                format!("<div class='setting-line'>\
-                                             <label class='toggle'>\
-                                                <input type='checkbox' id='{}' {}>\
-                                                <span class='slider'></span>\
-                                             </label>\
-                                             <div>{}</div>\
-                                         </div>", id, if *enabled { " checked" } else { "" }, text)
-                            })
-                            .collect::<String>(),
-               self.root_path,
-               self.suffix)
-    }
+            settings.iter()
+                        .map(|(id, text, enabled)| {
+                            format!("<div class='setting-line'>\
+                                            <label class='toggle'>\
+                                            <input type='checkbox' id='{}' {}>\
+                                            <span class='slider'></span>\
+                                            </label>\
+                                            <div>{}</div>\
+                                        </div>", id, if *enabled { " checked" } else { "" }, text)
+                        })
+                        .collect::<String>(),
+            root_path,
+            suffix)
 }
 
 impl Context {
@@ -1939,18 +1892,12 @@
         } else {
             String::new()
         };
-        let mut v = Vec::new();
-        try_err!(layout::render(&mut v, &self.shared.layout,
-                                &page, &sidebar, &all,
-                                self.shared.css_file_extension.is_some(),
-                                &self.shared.themes,
-                                self.shared.generate_search_filter),
-                 &final_file);
-        self.shared.fs.write(&final_file, &v)?;
+        let v = layout::render(&self.shared.layout,
+                       &page, sidebar, |buf: &mut Buffer| all.print(buf),
+                       &self.shared.themes);
+        self.shared.fs.write(&final_file, v.as_bytes())?;
 
         // Generating settings page.
-        let settings = Settings::new(self.shared.static_root_path.as_deref().unwrap_or("./"),
-                                     &self.shared.resource_suffix);
         page.title = "Rustdoc settings";
         page.description = "Settings of Rustdoc";
         page.root_path = "./";
@@ -1958,24 +1905,21 @@
         let mut themes = self.shared.themes.clone();
         let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>";
         themes.push(PathBuf::from("settings.css"));
-        let layout = self.shared.layout.clone();
-        let mut v = Vec::new();
-        try_err!(layout::render(&mut v, &layout,
-                                &page, &sidebar, &settings,
-                                self.shared.css_file_extension.is_some(),
-                                &themes,
-                                self.shared.generate_search_filter),
-                 &settings_file);
-        self.shared.fs.write(&settings_file, &v)?;
+        let v = layout::render(
+            &self.shared.layout,
+            &page, sidebar, settings(
+                self.shared.static_root_path.as_deref().unwrap_or("./"),
+                &self.shared.resource_suffix
+            ),
+            &themes);
+        self.shared.fs.write(&settings_file, v.as_bytes())?;
 
         Ok(())
     }
 
     fn render_item(&self,
-                   writer: &mut dyn io::Write,
                    it: &clean::Item,
-                   pushname: bool)
-                   -> io::Result<()> {
+                   pushname: bool) -> String {
         // A little unfortunate that this is done like this, but it sure
         // does make formatting *a lot* nicer.
         CURRENT_DEPTH.with(|slot| {
@@ -2022,12 +1966,10 @@
         }
 
         if !self.render_redirect_pages {
-            layout::render(writer, &self.shared.layout, &page,
-                           &Sidebar{ cx: self, item: it },
-                           &Item{ cx: self, item: it },
-                           self.shared.css_file_extension.is_some(),
-                           &self.shared.themes,
-                           self.shared.generate_search_filter)?;
+            layout::render(&self.shared.layout, &page,
+                           |buf: &mut _| print_sidebar(self, it, buf),
+                           |buf: &mut _| print_item(self, it, buf),
+                           &self.shared.themes)
         } else {
             let mut url = self.root_path();
             if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
@@ -2036,10 +1978,11 @@
                     url.push_str("/");
                 }
                 url.push_str(&item_path(ty, names.last().unwrap()));
-                layout::redirect(writer, &url)?;
+                layout::redirect(&url)
+            } else {
+                String::new()
             }
         }
-        Ok(())
     }
 
     /// Non-parallelized version of rendering an item. This will take the input
@@ -2075,13 +2018,12 @@
 
             info!("Recursing into {}", self.dst.display());
 
-            let mut buf = Vec::new();
-            self.render_item(&mut buf, &item, false).unwrap();
+            let buf = self.render_item(&item, false);
             // buf will be empty if the module is stripped and there is no redirect for it
             if !buf.is_empty() {
                 self.shared.ensure_dir(&self.dst)?;
                 let joint_dst = self.dst.join("index.html");
-                scx.fs.write(&joint_dst, buf)?;
+                scx.fs.write(&joint_dst, buf.as_bytes())?;
             }
 
             let m = match item.inner {
@@ -2094,9 +2036,7 @@
             if !self.render_redirect_pages {
                 let items = self.build_sidebar_items(&m);
                 let js_dst = self.dst.join("sidebar-items.js");
-                let mut v = Vec::new();
-                try_err!(write!(&mut v, "initSidebarItems({});",
-                                as_json(&items)), &js_dst);
+                let v = format!("initSidebarItems({});", as_json(&items));
                 scx.fs.write(&js_dst, &v)?;
             }
 
@@ -2110,8 +2050,7 @@
             self.dst = prev;
             self.current.pop().unwrap();
         } else if item.name.is_some() {
-            let mut buf = Vec::new();
-            self.render_item(&mut buf, &item, true).unwrap();
+            let buf = self.render_item(&item, true);
             // buf will be empty if the item is stripped and there is no redirect for it
             if !buf.is_empty() {
                 let name = item.name.as_ref().unwrap();
@@ -2119,7 +2058,7 @@
                 let file_name = &item_path(item_type, name);
                 self.shared.ensure_dir(&self.dst)?;
                 let joint_dst = self.dst.join(file_name);
-                self.shared.fs.write(&joint_dst, buf)?;
+                self.shared.fs.write(&joint_dst, buf.as_bytes())?;
 
                 if !self.render_redirect_pages {
                     all.append(full_path(self, &item), &item_type);
@@ -2129,18 +2068,16 @@
                     // URL for the page.
                     let redir_name = format!("{}.{}.html", name, item_type.name_space());
                     let redir_dst = self.dst.join(redir_name);
-                    let mut v = Vec::new();
-                    try_err!(layout::redirect(&mut v, file_name), &redir_dst);
-                    self.shared.fs.write(&redir_dst, &v)?;
+                    let v = layout::redirect(file_name);
+                    self.shared.fs.write(&redir_dst, v.as_bytes())?;
                 }
                 // If the item is a macro, redirect from the old macro URL (with !)
                 // to the new one (without).
                 if item_type == ItemType::Macro {
                     let redir_name = format!("{}.{}!.html", item_type, name);
                     let redir_dst = self.dst.join(redir_name);
-                    let mut v = Vec::new();
-                    try_err!(layout::redirect(&mut v, file_name), &redir_dst);
-                    self.shared.fs.write(&redir_dst, &v)?;
+                    let v = layout::redirect(file_name);
+                    self.shared.fs.write(&redir_dst, v.as_bytes())?;
                 }
             }
         }
@@ -2172,7 +2109,7 @@
     }
 }
 
-impl<'a> Item<'a> {
+impl Context {
     /// Generates a url appropriate for an `href` attribute back to the source of
     /// this item.
     ///
@@ -2182,26 +2119,26 @@
     /// If `None` is returned, then a source link couldn't be generated. This
     /// may happen, for example, with externally inlined items where the source
     /// of their crate documentation isn't known.
-    fn src_href(&self) -> Option<String> {
-        let mut root = self.cx.root_path();
+    fn src_href(&self, item: &clean::Item) -> Option<String> {
+        let mut root = self.root_path();
 
         let cache = cache();
         let mut path = String::new();
 
         // We can safely ignore macros from other libraries
-        let file = match self.item.source.filename {
+        let file = match item.source.filename {
             FileName::Real(ref path) => path,
             _ => return None,
         };
 
-        let (krate, path) = if self.item.def_id.is_local() {
-            if let Some(path) = self.cx.shared.local_sources.get(file) {
-                (&self.cx.shared.layout.krate, path)
+        let (krate, path) = if item.def_id.is_local() {
+            if let Some(path) = self.shared.local_sources.get(file) {
+                (&self.shared.layout.krate, path)
             } else {
                 return None;
             }
         } else {
-            let (krate, src_root) = match *cache.extern_locations.get(&self.item.def_id.krate)? {
+            let (krate, src_root) = match *cache.extern_locations.get(&item.def_id.krate)? {
                 (ref name, ref src, Local) => (name, src),
                 (ref name, ref src, Remote(ref s)) => {
                     root = s.to_string();
@@ -2221,10 +2158,10 @@
             (krate, &path)
         };
 
-        let lines = if self.item.source.loline == self.item.source.hiline {
-            self.item.source.loline.to_string()
+        let lines = if item.source.loline == item.source.hiline {
+            item.source.loline.to_string()
         } else {
-            format!("{}-{}", self.item.source.loline, self.item.source.hiline)
+            format!("{}-{}", item.source.loline, item.source.hiline)
         };
         Some(format!("{root}src/{krate}/{path}#{lines}",
                      root = Escape(&root),
@@ -2234,114 +2171,113 @@
     }
 }
 
-fn wrap_into_docblock<F>(w: &mut fmt::Formatter<'_>,
-                         f: F) -> fmt::Result
-where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result {
-    write!(w, "<div class=\"docblock type-decl hidden-by-usual-hider\">")?;
-    f(w)?;
+fn wrap_into_docblock<F>(w: &mut Buffer, f: F)
+    where F: FnOnce(&mut Buffer)
+{
+    write!(w, "<div class=\"docblock type-decl hidden-by-usual-hider\">");
+    f(w);
     write!(w, "</div>")
 }
 
-impl<'a> fmt::Display for Item<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        debug_assert!(!self.item.is_stripped());
-        // Write the breadcrumb trail header for the top
-        write!(fmt, "<h1 class='fqn'><span class='out-of-band'>")?;
-        if let Some(version) = self.item.stable_since() {
-            write!(fmt, "<span class='since' title='Stable since Rust version {0}'>{0}</span>",
-                   version)?;
-        }
-        write!(fmt,
-               "<span id='render-detail'>\
-                   <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" \
-                      title=\"collapse all docs\">\
-                       [<span class='inner'>&#x2212;</span>]\
-                   </a>\
-               </span>")?;
+fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) {
+    debug_assert!(!item.is_stripped());
+    // Write the breadcrumb trail header for the top
+    write!(buf, "<h1 class='fqn'><span class='out-of-band'>");
+    if let Some(version) = item.stable_since() {
+        write!(buf, "<span class='since' title='Stable since Rust version {0}'>{0}</span>",
+                version);
+    }
+    write!(buf,
+            "<span id='render-detail'>\
+                <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" \
+                    title=\"collapse all docs\">\
+                    [<span class='inner'>&#x2212;</span>]\
+                </a>\
+            </span>");
 
-        // Write `src` tag
-        //
-        // When this item is part of a `pub use` in a downstream crate, the
-        // [src] link in the downstream documentation will actually come back to
-        // this page, and this link will be auto-clicked. The `id` attribute is
-        // used to find the link to auto-click.
-        if self.cx.shared.include_sources && !self.item.is_primitive() {
-            if let Some(l) = self.src_href() {
-                write!(fmt, "<a class='srclink' href='{}' title='{}'>[src]</a>",
-                       l, "goto source code")?;
-            }
+    // Write `src` tag
+    //
+    // When this item is part of a `pub use` in a downstream crate, the
+    // [src] link in the downstream documentation will actually come back to
+    // this page, and this link will be auto-clicked. The `id` attribute is
+    // used to find the link to auto-click.
+    if cx.shared.include_sources && !item.is_primitive() {
+        if let Some(l) = cx.src_href(item) {
+            write!(buf, "<a class='srclink' href='{}' title='{}'>[src]</a>",
+                    l, "goto source code");
         }
+    }
 
-        write!(fmt, "</span>")?; // out-of-band
-        write!(fmt, "<span class='in-band'>")?;
-        match self.item.inner {
-            clean::ModuleItem(ref m) => if m.is_crate {
-                    write!(fmt, "Crate ")?;
-                } else {
-                    write!(fmt, "Module ")?;
-                },
-            clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => write!(fmt, "Function ")?,
-            clean::TraitItem(..) => write!(fmt, "Trait ")?,
-            clean::StructItem(..) => write!(fmt, "Struct ")?,
-            clean::UnionItem(..) => write!(fmt, "Union ")?,
-            clean::EnumItem(..) => write!(fmt, "Enum ")?,
-            clean::TypedefItem(..) => write!(fmt, "Type Definition ")?,
-            clean::MacroItem(..) => write!(fmt, "Macro ")?,
-            clean::ProcMacroItem(ref mac) => match mac.kind {
-                MacroKind::Bang => write!(fmt, "Macro ")?,
-                MacroKind::Attr => write!(fmt, "Attribute Macro ")?,
-                MacroKind::Derive => write!(fmt, "Derive Macro ")?,
-            }
-            clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?,
-            clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?,
-            clean::ConstantItem(..) => write!(fmt, "Constant ")?,
-            clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?,
-            clean::KeywordItem(..) => write!(fmt, "Keyword ")?,
-            clean::OpaqueTyItem(..) => write!(fmt, "Opaque Type ")?,
-            clean::TraitAliasItem(..) => write!(fmt, "Trait Alias ")?,
-            _ => {
-                // We don't generate pages for any other type.
-                unreachable!();
-            }
+    write!(buf, "</span>"); // out-of-band
+    write!(buf, "<span class='in-band'>");
+    let name = match item.inner {
+        clean::ModuleItem(ref m) => if m.is_crate {
+                "Crate "
+            } else {
+                "Module "
+            },
+        clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => "Function ",
+        clean::TraitItem(..) => "Trait ",
+        clean::StructItem(..) => "Struct ",
+        clean::UnionItem(..) => "Union ",
+        clean::EnumItem(..) => "Enum ",
+        clean::TypedefItem(..) => "Type Definition ",
+        clean::MacroItem(..) => "Macro ",
+        clean::ProcMacroItem(ref mac) => match mac.kind {
+            MacroKind::Bang => "Macro ",
+            MacroKind::Attr => "Attribute Macro ",
+            MacroKind::Derive => "Derive Macro ",
         }
-        if !self.item.is_primitive() && !self.item.is_keyword() {
-            let cur = &self.cx.current;
-            let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() };
-            for (i, component) in cur.iter().enumerate().take(amt) {
-                write!(fmt, "<a href='{}index.html'>{}</a>::<wbr>",
-                       "../".repeat(cur.len() - i - 1),
-                       component)?;
-            }
+        clean::PrimitiveItem(..) => "Primitive Type ",
+        clean::StaticItem(..) | clean::ForeignStaticItem(..) => "Static ",
+        clean::ConstantItem(..) => "Constant ",
+        clean::ForeignTypeItem => "Foreign Type ",
+        clean::KeywordItem(..) => "Keyword ",
+        clean::OpaqueTyItem(..) => "Opaque Type ",
+        clean::TraitAliasItem(..) => "Trait Alias ",
+        _ => {
+            // We don't generate pages for any other type.
+            unreachable!();
         }
-        write!(fmt, "<a class=\"{}\" href=''>{}</a>",
-               self.item.type_(), self.item.name.as_ref().unwrap())?;
+    };
+    buf.write_str(name);
+    if !item.is_primitive() && !item.is_keyword() {
+        let cur = &cx.current;
+        let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() };
+        for (i, component) in cur.iter().enumerate().take(amt) {
+            write!(buf, "<a href='{}index.html'>{}</a>::<wbr>",
+                    "../".repeat(cur.len() - i - 1),
+                    component);
+        }
+    }
+    write!(buf, "<a class=\"{}\" href=''>{}</a>",
+            item.type_(), item.name.as_ref().unwrap());
 
-        write!(fmt, "</span></h1>")?; // in-band
+    write!(buf, "</span></h1>"); // in-band
 
-        match self.item.inner {
-            clean::ModuleItem(ref m) =>
-                item_module(fmt, self.cx, self.item, &m.items),
-            clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) =>
-                item_function(fmt, self.cx, self.item, f),
-            clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t),
-            clean::StructItem(ref s) => item_struct(fmt, self.cx, self.item, s),
-            clean::UnionItem(ref s) => item_union(fmt, self.cx, self.item, s),
-            clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e),
-            clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t),
-            clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m),
-            clean::ProcMacroItem(ref m) => item_proc_macro(fmt, self.cx, self.item, m),
-            clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p),
-            clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) =>
-                item_static(fmt, self.cx, self.item, i),
-            clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c),
-            clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item),
-            clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k),
-            clean::OpaqueTyItem(ref e, _) => item_opaque_ty(fmt, self.cx, self.item, e),
-            clean::TraitAliasItem(ref ta) => item_trait_alias(fmt, self.cx, self.item, ta),
-            _ => {
-                // We don't generate pages for any other type.
-                unreachable!();
-            }
+    match item.inner {
+        clean::ModuleItem(ref m) =>
+            item_module(buf, cx, item, &m.items),
+        clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) =>
+            item_function(buf, cx, item, f),
+        clean::TraitItem(ref t) => item_trait(buf, cx, item, t),
+        clean::StructItem(ref s) => item_struct(buf, cx, item, s),
+        clean::UnionItem(ref s) => item_union(buf, cx, item, s),
+        clean::EnumItem(ref e) => item_enum(buf, cx, item, e),
+        clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t),
+        clean::MacroItem(ref m) => item_macro(buf, cx, item, m),
+        clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m),
+        clean::PrimitiveItem(ref p) => item_primitive(buf, cx, item, p),
+        clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) =>
+            item_static(buf, cx, item, i),
+        clean::ConstantItem(ref c) => item_constant(buf, cx, item, c),
+        clean::ForeignTypeItem => item_foreign_type(buf, cx, item),
+        clean::KeywordItem(ref k) => item_keyword(buf, cx, item, k),
+        clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e),
+        clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta),
+        _ => {
+            // We don't generate pages for any other type.
+            unreachable!();
         }
     }
 }
@@ -2395,24 +2331,23 @@
     }
 }
 
-fn document(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item) -> fmt::Result {
+fn document(w: &mut Buffer, cx: &Context, item: &clean::Item) {
     if let Some(ref name) = item.name {
         info!("Documenting {}", name);
     }
-    document_stability(w, cx, item, false)?;
-    document_full(w, item, cx, "", false)?;
-    Ok(())
+    document_stability(w, cx, item, false);
+    document_full(w, item, cx, "", false);
 }
 
 /// Render md_text as markdown.
 fn render_markdown(
-    w: &mut fmt::Formatter<'_>,
+    w: &mut Buffer,
     cx: &Context,
     md_text: &str,
     links: Vec<(String, String)>,
     prefix: &str,
     is_hidden: bool,
-) -> fmt::Result {
+) {
     let mut ids = cx.id_map.borrow_mut();
     write!(w, "<div class='docblock{}'>{}{}</div>",
            if is_hidden { " hidden" } else { "" },
@@ -2422,13 +2357,13 @@
 }
 
 fn document_short(
-    w: &mut fmt::Formatter<'_>,
+    w: &mut Buffer,
     cx: &Context,
     item: &clean::Item,
     link: AssocItemLink<'_>,
     prefix: &str,
     is_hidden: bool,
-) -> fmt::Result {
+) {
     if let Some(s) = item.doc_value() {
         let markdown = if s.contains('\n') {
             format!("{} [Read more]({})",
@@ -2436,46 +2371,41 @@
         } else {
             plain_summary_line(Some(s))
         };
-        render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden)?;
+        render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden);
     } else if !prefix.is_empty() {
         write!(w, "<div class='docblock{}'>{}</div>",
                if is_hidden { " hidden" } else { "" },
-               prefix)?;
+               prefix);
     }
-    Ok(())
 }
 
-fn document_full(w: &mut fmt::Formatter<'_>, item: &clean::Item,
-                 cx: &Context, prefix: &str, is_hidden: bool) -> fmt::Result {
+fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context, prefix: &str, is_hidden: bool) {
     if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
         debug!("Doc block: =====\n{}\n=====", s);
-        render_markdown(w, cx, &*s, item.links(), prefix, is_hidden)?;
+        render_markdown(w, cx, &*s, item.links(), prefix, is_hidden);
     } else if !prefix.is_empty() {
         write!(w, "<div class='docblock{}'>{}</div>",
                if is_hidden { " hidden" } else { "" },
-               prefix)?;
+               prefix);
     }
-    Ok(())
 }
 
-fn document_stability(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item,
-                      is_hidden: bool) -> fmt::Result {
+fn document_stability(w: &mut Buffer, cx: &Context, item: &clean::Item, is_hidden: bool) {
     let stabilities = short_stability(item, cx);
     if !stabilities.is_empty() {
-        write!(w, "<div class='stability{}'>", if is_hidden { " hidden" } else { "" })?;
+        write!(w, "<div class='stability{}'>", if is_hidden { " hidden" } else { "" });
         for stability in stabilities {
-            write!(w, "{}", stability)?;
+            write!(w, "{}", stability);
         }
-        write!(w, "</div>")?;
+        write!(w, "</div>");
     }
-    Ok(())
 }
 
 fn document_non_exhaustive_header(item: &clean::Item) -> &str {
     if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" }
 }
 
-fn document_non_exhaustive(w: &mut fmt::Formatter<'_>, item: &clean::Item) -> fmt::Result {
+fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) {
     if item.is_non_exhaustive() {
         write!(w, "<div class='docblock non-exhaustive non-exhaustive-{}'>", {
             if item.is_struct() {
@@ -2487,31 +2417,29 @@
             } else {
                 "type"
             }
-        })?;
+        });
 
         if item.is_struct() {
             write!(w, "Non-exhaustive structs could have additional fields added in future. \
                        Therefore, non-exhaustive structs cannot be constructed in external crates \
                        using the traditional <code>Struct {{ .. }}</code> syntax; cannot be \
                        matched against without a wildcard <code>..</code>; and \
-                       struct update syntax will not work.")?;
+                       struct update syntax will not work.");
         } else if item.is_enum() {
             write!(w, "Non-exhaustive enums could have additional variants added in future. \
                        Therefore, when matching against variants of non-exhaustive enums, an \
-                       extra wildcard arm must be added to account for any future variants.")?;
+                       extra wildcard arm must be added to account for any future variants.");
         } else if item.is_variant() {
             write!(w, "Non-exhaustive enum variants could have additional fields added in future. \
                        Therefore, non-exhaustive enum variants cannot be constructed in external \
-                       crates and cannot be matched against.")?;
+                       crates and cannot be matched against.");
         } else {
             write!(w, "This type will require a wildcard arm in any match statements or \
-                       constructors.")?;
+                       constructors.");
         }
 
-        write!(w, "</div>")?;
+        write!(w, "</div>");
     }
-
-    Ok(())
 }
 
 fn name_key(name: &str) -> (&str, u64, usize) {
@@ -2535,9 +2463,8 @@
     }
 }
 
-fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context,
-               item: &clean::Item, items: &[clean::Item]) -> fmt::Result {
-    document(w, cx, item)?;
+fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) {
+    document(w, cx, item);
 
     let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>();
 
@@ -2628,13 +2555,13 @@
             curty = myty;
         } else if myty != curty {
             if curty.is_some() {
-                write!(w, "</table>")?;
+                write!(w, "</table>");
             }
             curty = myty;
             let (short, name) = item_ty_to_strs(&myty.unwrap());
             write!(w, "<h2 id='{id}' class='section-header'>\
                        <a href=\"#{id}\">{name}</a></h2>\n<table>",
-                   id = cx.derive_id(short.to_owned()), name = name)?;
+                   id = cx.derive_id(short.to_owned()), name = name);
         }
 
         match myitem.inner {
@@ -2646,20 +2573,20 @@
                         write!(w, "<tr><td><code>{}extern crate {} as {};",
                                VisSpace(&myitem.visibility),
                                anchor(myitem.def_id, src),
-                               name)?
+                               name)
                     }
                     None => {
                         write!(w, "<tr><td><code>{}extern crate {};",
                                VisSpace(&myitem.visibility),
-                               anchor(myitem.def_id, name))?
+                               anchor(myitem.def_id, name))
                     }
                 }
-                write!(w, "</code></td></tr>")?;
+                write!(w, "</code></td></tr>");
             }
 
             clean::ImportItem(ref import) => {
                 write!(w, "<tr><td><code>{}{}</code></td></tr>",
-                       VisSpace(&myitem.visibility), *import)?;
+                       VisSpace(&myitem.visibility), *import);
             }
 
             _ => {
@@ -2704,15 +2631,14 @@
                                 })
                                 .collect::<Vec<_>>()
                                 .join(" "),
-                      )?;
+                      );
             }
         }
     }
 
     if curty.is_some() {
-        write!(w, "</table>")?;
+        write!(w, "</table>");
     }
-    Ok(())
 }
 
 /// Render the stability and deprecation tags that are displayed in the item's summary at the
@@ -2861,33 +2787,30 @@
     stability
 }
 
-fn item_constant(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
-                 c: &clean::Constant) -> fmt::Result {
-    write!(w, "<pre class='rust const'>")?;
-    render_attributes(w, it, false)?;
+fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Constant) {
+    write!(w, "<pre class='rust const'>");
+    render_attributes(w, it, false);
     write!(w, "{vis}const \
                {name}: {typ}</pre>",
            vis = VisSpace(&it.visibility),
            name = it.name.as_ref().unwrap(),
-           typ = c.type_)?;
+           typ = c.type_);
     document(w, cx, it)
 }
 
-fn item_static(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
-               s: &clean::Static) -> fmt::Result {
-    write!(w, "<pre class='rust static'>")?;
-    render_attributes(w, it, false)?;
+fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static) {
+    write!(w, "<pre class='rust static'>");
+    render_attributes(w, it, false);
     write!(w, "{vis}static {mutability}\
                {name}: {typ}</pre>",
            vis = VisSpace(&it.visibility),
            mutability = MutableSpace(s.mutability),
            name = it.name.as_ref().unwrap(),
-           typ = s.type_)?;
+           typ = s.type_);
     document(w, cx, it)
 }
 
-fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
-                 f: &clean::Function) -> fmt::Result {
+fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Function) {
     let header_len = format!(
         "{}{}{}{}{:#}fn {}{:#}",
         VisSpace(&it.visibility),
@@ -2898,8 +2821,8 @@
         it.name.as_ref().unwrap(),
         f.generics
     ).len();
-    write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it)?)?;
-    render_attributes(w, it, false)?;
+    write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it));
+    render_attributes(w, it, false);
     write!(w,
            "{vis}{constness}{unsafety}{asyncness}{abi}fn \
            {name}{generics}{decl}{where_clause}</pre>",
@@ -2916,12 +2839,12 @@
               header_len,
               indent: 0,
               asyncness: f.header.asyncness,
-           })?;
+           });
     document(w, cx, it)
 }
 
-fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter<'_>,
-                      implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> fmt::Result {
+fn render_implementor(cx: &Context, implementor: &Impl, w: &mut Buffer,
+                      implementor_dups: &FxHashMap<&str, (DefId, bool)>) {
     // If there's already another implementor that has the same abbridged name, use the
     // full path, for example in `std::iter::ExactSizeIterator`
     let use_absolute = match implementor.inner_impl().for_ {
@@ -2933,20 +2856,18 @@
         _ => false,
     };
     render_impl(w, cx, implementor, AssocItemLink::Anchor(None), RenderMode::Normal,
-                implementor.impl_item.stable_since(), false, Some(use_absolute), false, false)?;
-    Ok(())
+                implementor.impl_item.stable_since(), false, Some(use_absolute), false, false);
 }
 
-fn render_impls(cx: &Context, w: &mut fmt::Formatter<'_>,
+fn render_impls(cx: &Context, w: &mut Buffer,
                 traits: &[&&Impl],
-                containing_item: &clean::Item) -> fmt::Result {
+                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)?;
+                    RenderMode::Normal, containing_item.stable_since(), true, None, false, true);
     }
-    Ok(())
 }
 
 fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool) -> String {
@@ -2974,11 +2895,11 @@
 }
 
 fn item_trait(
-    w: &mut fmt::Formatter<'_>,
+    w: &mut Buffer,
     cx: &Context,
     it: &clean::Item,
     t: &clean::Trait,
-) -> fmt::Result {
+) {
     let bounds = bounds(&t.bounds, false);
     let types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
     let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
@@ -2987,146 +2908,144 @@
 
     // Output the trait definition
     wrap_into_docblock(w, |w| {
-        write!(w, "<pre class='rust trait'>")?;
-        render_attributes(w, it, true)?;
+        write!(w, "<pre class='rust trait'>");
+        render_attributes(w, it, true);
         write!(w, "{}{}{}trait {}{}{}",
                VisSpace(&it.visibility),
                UnsafetySpace(t.unsafety),
                if t.is_auto { "auto " } else { "" },
                it.name.as_ref().unwrap(),
                t.generics,
-               bounds)?;
+               bounds);
 
         if !t.generics.where_predicates.is_empty() {
-            write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true })?;
+            write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true });
         } else {
-            write!(w, " ")?;
+            write!(w, " ");
         }
 
         if t.items.is_empty() {
-            write!(w, "{{ }}")?;
+            write!(w, "{{ }}");
         } else {
             // FIXME: we should be using a derived_id for the Anchors here
-            write!(w, "{{\n")?;
+            write!(w, "{{\n");
             for t in &types {
-                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
-                write!(w, ";\n")?;
+                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait);
+                write!(w, ";\n");
             }
             if !types.is_empty() && !consts.is_empty() {
-                w.write_str("\n")?;
+                w.write_str("\n");
             }
             for t in &consts {
-                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
-                write!(w, ";\n")?;
+                render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait);
+                write!(w, ";\n");
             }
             if !consts.is_empty() && !required.is_empty() {
-                w.write_str("\n")?;
+                w.write_str("\n");
             }
             for (pos, m) in required.iter().enumerate() {
-                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
-                write!(w, ";\n")?;
+                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait);
+                write!(w, ";\n");
 
                 if pos < required.len() - 1 {
-                   write!(w, "<div class='item-spacer'></div>")?;
+                   write!(w, "<div class='item-spacer'></div>");
                 }
             }
             if !required.is_empty() && !provided.is_empty() {
-                w.write_str("\n")?;
+                w.write_str("\n");
             }
             for (pos, m) in provided.iter().enumerate() {
-                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
+                render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait);
                 match m.inner {
                     clean::MethodItem(ref inner) if !inner.generics.where_predicates.is_empty() => {
-                        write!(w, ",\n    {{ ... }}\n")?;
+                        write!(w, ",\n    {{ ... }}\n");
                     },
                     _ => {
-                        write!(w, " {{ ... }}\n")?;
+                        write!(w, " {{ ... }}\n");
                     },
                 }
                 if pos < provided.len() - 1 {
-                   write!(w, "<div class='item-spacer'></div>")?;
+                   write!(w, "<div class='item-spacer'></div>");
                 }
             }
-            write!(w, "}}")?;
+            write!(w, "}}");
         }
         write!(w, "</pre>")
-    })?;
+    });
 
     // Trait documentation
-    document(w, cx, it)?;
+    document(w, cx, it);
 
     fn write_small_section_header(
-        w: &mut fmt::Formatter<'_>,
+        w: &mut Buffer,
         id: &str,
         title: &str,
         extra_content: &str,
-    ) -> fmt::Result {
+    ) {
         write!(w, "
             <h2 id='{0}' class='small-section-header'>\
               {1}<a href='#{0}' class='anchor'></a>\
             </h2>{2}", id, title, extra_content)
     }
 
-    fn write_loading_content(w: &mut fmt::Formatter<'_>, extra_content: &str) -> fmt::Result {
+    fn write_loading_content(w: &mut Buffer, extra_content: &str) {
         write!(w, "{}<span class='loading-content'>Loading content...</span>", extra_content)
     }
 
-    fn trait_item(w: &mut fmt::Formatter<'_>, cx: &Context, m: &clean::Item, t: &clean::Item)
-                  -> fmt::Result {
+    fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
         let name = m.name.as_ref().unwrap();
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
         let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
         write!(w, "<h3 id='{id}' class='method'>{extra}<code id='{ns_id}'>",
-               extra = render_spotlight_traits(m)?,
+               extra = render_spotlight_traits(m),
                id = id,
-               ns_id = ns_id)?;
-        render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?;
-        write!(w, "</code>")?;
-        render_stability_since(w, m, t)?;
-        write!(w, "</h3>")?;
-        document(w, cx, m)?;
-        Ok(())
+               ns_id = ns_id);
+        render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
+        write!(w, "</code>");
+        render_stability_since(w, m, t);
+        write!(w, "</h3>");
+        document(w, cx, m);
     }
 
     if !types.is_empty() {
         write_small_section_header(w, "associated-types", "Associated Types",
-                                   "<div class='methods'>")?;
+                                   "<div class='methods'>");
         for t in &types {
-            trait_item(w, cx, *t, it)?;
+            trait_item(w, cx, *t, it);
         }
-        write_loading_content(w, "</div>")?;
+        write_loading_content(w, "</div>");
     }
 
     if !consts.is_empty() {
         write_small_section_header(w, "associated-const", "Associated Constants",
-                                   "<div class='methods'>")?;
+                                   "<div class='methods'>");
         for t in &consts {
-            trait_item(w, cx, *t, it)?;
+            trait_item(w, cx, *t, it);
         }
-        write_loading_content(w, "</div>")?;
+        write_loading_content(w, "</div>");
     }
 
     // Output the documentation for each function individually
     if !required.is_empty() {
         write_small_section_header(w, "required-methods", "Required methods",
-                                   "<div class='methods'>")?;
+                                   "<div class='methods'>");
         for m in &required {
-            trait_item(w, cx, *m, it)?;
+            trait_item(w, cx, *m, it);
         }
-        write_loading_content(w, "</div>")?;
+        write_loading_content(w, "</div>");
     }
     if !provided.is_empty() {
         write_small_section_header(w, "provided-methods", "Provided methods",
-                                   "<div class='methods'>")?;
+                                   "<div class='methods'>");
         for m in &provided {
-            trait_item(w, cx, *m, it)?;
+            trait_item(w, cx, *m, it);
         }
-        write_loading_content(w, "</div>")?;
+        write_loading_content(w, "</div>");
     }
 
     // If there are methods directly on this trait object, render them here.
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?;
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All);
 
     let cache = cache();
 
@@ -3165,7 +3084,7 @@
         concrete.sort_by(compare_impl);
 
         if !foreign.is_empty() {
-            write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "")?;
+            write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "");
 
             for implementor in foreign {
                 let assoc_link = AssocItemLink::GotoSource(
@@ -3174,44 +3093,44 @@
                 );
                 render_impl(w, cx, &implementor, assoc_link,
                             RenderMode::Normal, implementor.impl_item.stable_since(), false,
-                            None, true, false)?;
+                            None, true, false);
             }
-            write_loading_content(w, "")?;
+            write_loading_content(w, "");
         }
 
         write_small_section_header(w, "implementors", "Implementors",
-                                   "<div class='item-list' id='implementors-list'>")?;
+                                   "<div class='item-list' id='implementors-list'>");
         for implementor in concrete {
-            render_implementor(cx, implementor, w, &implementor_dups)?;
+            render_implementor(cx, implementor, w, &implementor_dups);
         }
-        write_loading_content(w, "</div>")?;
+        write_loading_content(w, "</div>");
 
         if t.auto {
             write_small_section_header(w, "synthetic-implementors", "Auto implementors",
-                                       "<div class='item-list' id='synthetic-implementors-list'>")?;
+                                       "<div class='item-list' id='synthetic-implementors-list'>");
             for implementor in synthetic {
                 synthetic_types.extend(
                     collect_paths_for_type(implementor.inner_impl().for_.clone())
                 );
-                render_implementor(cx, implementor, w, &implementor_dups)?;
+                render_implementor(cx, implementor, w, &implementor_dups);
             }
-            write_loading_content(w, "</div>")?;
+            write_loading_content(w, "</div>");
         }
     } else {
         // even without any implementations to write in, we still want the heading and list, so the
         // implementors javascript file pulled in below has somewhere to write the impls into
         write_small_section_header(w, "implementors", "Implementors",
-                                   "<div class='item-list' id='implementors-list'>")?;
-        write_loading_content(w, "</div>")?;
+                                   "<div class='item-list' id='implementors-list'>");
+        write_loading_content(w, "</div>");
 
         if t.auto {
             write_small_section_header(w, "synthetic-implementors", "Auto implementors",
-                                       "<div class='item-list' id='synthetic-implementors-list'>")?;
-            write_loading_content(w, "</div>")?;
+                                       "<div class='item-list' id='synthetic-implementors-list'>");
+            write_loading_content(w, "</div>");
         }
     }
     write!(w, r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#,
-           as_json(&synthetic_types))?;
+           as_json(&synthetic_types));
 
     write!(w, r#"<script type="text/javascript" async
                          src="{root_path}/implementors/{path}/{ty}.{name}.js">
@@ -3224,8 +3143,7 @@
                path[..path.len() - 1].join("/")
            },
            ty = it.type_().css_class(),
-           name = *it.name.as_ref().unwrap())?;
-    Ok(())
+           name = *it.name.as_ref().unwrap());
 }
 
 fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>) -> String {
@@ -3247,70 +3165,60 @@
     }
 }
 
-fn assoc_const(w: &mut fmt::Formatter<'_>,
+fn assoc_const(w: &mut Buffer,
                it: &clean::Item,
                ty: &clean::Type,
                _default: Option<&String>,
                link: AssocItemLink<'_>,
-               extra: &str) -> fmt::Result {
+               extra: &str) {
     write!(w, "{}{}const <a href='{}' class=\"constant\"><b>{}</b></a>: {}",
            extra,
            VisSpace(&it.visibility),
            naive_assoc_href(it, link),
            it.name.as_ref().unwrap(),
-           ty)?;
-    Ok(())
+           ty);
 }
 
-fn assoc_type<W: fmt::Write>(w: &mut W, it: &clean::Item,
-                             bounds: &[clean::GenericBound],
-                             default: Option<&clean::Type>,
-                             link: AssocItemLink<'_>,
-                             extra: &str) -> fmt::Result {
+fn assoc_type(w: &mut Buffer, it: &clean::Item,
+              bounds: &[clean::GenericBound],
+              default: Option<&clean::Type>,
+              link: AssocItemLink<'_>,
+              extra: &str) {
     write!(w, "{}type <a href='{}' class=\"type\">{}</a>",
            extra,
            naive_assoc_href(it, link),
-           it.name.as_ref().unwrap())?;
+           it.name.as_ref().unwrap());
     if !bounds.is_empty() {
-        write!(w, ": {}", GenericBounds(bounds))?
+        write!(w, ": {}", GenericBounds(bounds))
     }
     if let Some(default) = default {
-        write!(w, " = {}", default)?;
+        write!(w, " = {}", default)
     }
-    Ok(())
 }
 
-fn render_stability_since_raw<'a, T: fmt::Write>(
-    w: &mut T,
-    ver: Option<&'a str>,
-    containing_ver: Option<&'a str>,
-) -> fmt::Result {
+fn render_stability_since_raw(w: &mut Buffer, ver: Option<&str>, containing_ver: Option<&str>) {
     if let Some(v) = ver {
         if containing_ver != ver && v.len() > 0 {
-            write!(w, "<span class='since' title='Stable since Rust version {0}'>{0}</span>", v)?
+            write!(w, "<span class='since' title='Stable since Rust version {0}'>{0}</span>", v)
         }
     }
-    Ok(())
 }
 
-fn render_stability_since(w: &mut fmt::Formatter<'_>,
-                          item: &clean::Item,
-                          containing_item: &clean::Item) -> fmt::Result {
+fn render_stability_since(w: &mut Buffer, item: &clean::Item, containing_item: &clean::Item) {
     render_stability_since_raw(w, item.stable_since(), containing_item.stable_since())
 }
 
-fn render_assoc_item(w: &mut fmt::Formatter<'_>,
+fn render_assoc_item(w: &mut Buffer,
                      item: &clean::Item,
                      link: AssocItemLink<'_>,
-                     parent: ItemType) -> fmt::Result {
-    fn method(w: &mut fmt::Formatter<'_>,
+                     parent: ItemType) {
+    fn method(w: &mut Buffer,
               meth: &clean::Item,
               header: hir::FnHeader,
               g: &clean::Generics,
               d: &clean::FnDecl,
               link: AssocItemLink<'_>,
-              parent: ItemType)
-              -> fmt::Result {
+              parent: ItemType) {
         let name = meth.name.as_ref().unwrap();
         let anchor = format!("#{}.{}", meth.type_(), name);
         let href = match link {
@@ -3345,7 +3253,7 @@
         } else {
             (0, true)
         };
-        render_attributes(w, meth, false)?;
+        render_attributes(w, meth, false);
         write!(w, "{}{}{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
                if parent == ItemType::Trait { "    " } else { "" },
@@ -3371,7 +3279,7 @@
                })
     }
     match item.inner {
-        clean::StrippedItem(..) => Ok(()),
+        clean::StrippedItem(..) => {},
         clean::TyMethodItem(ref m) => {
             method(w, item, m.header, &m.generics, &m.decl, link, parent)
         }
@@ -3390,22 +3298,21 @@
     }
 }
 
-fn item_struct(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
-               s: &clean::Struct) -> fmt::Result {
+fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct) {
     wrap_into_docblock(w, |w| {
-        write!(w, "<pre class='rust struct'>")?;
-        render_attributes(w, it, true)?;
+        write!(w, "<pre class='rust struct'>");
+        render_attributes(w, it, true);
         render_struct(w,
                       it,
                       Some(&s.generics),
                       s.struct_type,
                       &s.fields,
                       "",
-                      true)?;
+                      true);
         write!(w, "</pre>")
-    })?;
+    });
 
-    document(w, cx, it)?;
+    document(w, cx, it);
     let mut fields = s.fields.iter().filter_map(|f| {
         match f.inner {
             clean::StructFieldItem(ref ty) => Some((f, ty)),
@@ -3416,8 +3323,8 @@
         if fields.peek().is_some() {
             write!(w, "<h2 id='fields' class='fields small-section-header'>
                        Fields{}<a href='#fields' class='anchor'></a></h2>",
-                       document_non_exhaustive_header(it))?;
-            document_non_exhaustive(w, it)?;
+                       document_non_exhaustive_header(it));
+            document_non_exhaustive(w, it);
             for (field, ty) in fields {
                 let id = cx.derive_id(format!("{}.{}",
                                            ItemType::StructField,
@@ -3433,29 +3340,28 @@
                        id = id,
                        ns_id = ns_id,
                        name = field.name.as_ref().unwrap(),
-                       ty = ty)?;
-                document(w, cx, field)?;
+                       ty = ty);
+                document(w, cx, field);
             }
         }
     }
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn item_union(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
-               s: &clean::Union) -> fmt::Result {
+fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union) {
     wrap_into_docblock(w, |w| {
-        write!(w, "<pre class='rust union'>")?;
-        render_attributes(w, it, true)?;
+        write!(w, "<pre class='rust union'>");
+        render_attributes(w, it, true);
         render_union(w,
                      it,
                      Some(&s.generics),
                      &s.fields,
                      "",
-                     true)?;
+                     true);
         write!(w, "</pre>")
-    })?;
+    });
 
-    document(w, cx, it)?;
+    document(w, cx, it);
     let mut fields = s.fields.iter().filter_map(|f| {
         match f.inner {
             clean::StructFieldItem(ref ty) => Some((f, ty)),
@@ -3464,7 +3370,7 @@
     }).peekable();
     if fields.peek().is_some() {
         write!(w, "<h2 id='fields' class='fields small-section-header'>
-                   Fields<a href='#fields' class='anchor'></a></h2>")?;
+                   Fields<a href='#fields' class='anchor'></a></h2>");
         for (field, ty) in fields {
             let name = field.name.as_ref().expect("union field name");
             let id = format!("{}.{}", ItemType::StructField, name);
@@ -3475,47 +3381,46 @@
                    id = id,
                    name = name,
                    shortty = ItemType::StructField,
-                   ty = ty)?;
+                   ty = ty);
             if let Some(stability_class) = field.stability_class() {
                 write!(w, "<span class='stab {stab}'></span>",
-                    stab = stability_class)?;
+                    stab = stability_class);
             }
-            document(w, cx, field)?;
+            document(w, cx, field);
         }
     }
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
-             e: &clean::Enum) -> fmt::Result {
+fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
     wrap_into_docblock(w, |w| {
-        write!(w, "<pre class='rust enum'>")?;
-        render_attributes(w, it, true)?;
+        write!(w, "<pre class='rust enum'>");
+        render_attributes(w, it, true);
         write!(w, "{}enum {}{}{}",
                VisSpace(&it.visibility),
                it.name.as_ref().unwrap(),
                e.generics,
-               WhereClause { gens: &e.generics, indent: 0, end_newline: true })?;
+               WhereClause { gens: &e.generics, indent: 0, end_newline: true });
         if e.variants.is_empty() && !e.variants_stripped {
-            write!(w, " {{}}")?;
+            write!(w, " {{}}");
         } else {
-            write!(w, " {{\n")?;
+            write!(w, " {{\n");
             for v in &e.variants {
-                write!(w, "    ")?;
+                write!(w, "    ");
                 let name = v.name.as_ref().unwrap();
                 match v.inner {
                     clean::VariantItem(ref var) => {
                         match var.kind {
-                            clean::VariantKind::CLike => write!(w, "{}", name)?,
+                            clean::VariantKind::CLike => write!(w, "{}", name),
                             clean::VariantKind::Tuple(ref tys) => {
-                                write!(w, "{}(", name)?;
+                                write!(w, "{}(", name);
                                 for (i, ty) in tys.iter().enumerate() {
                                     if i > 0 {
-                                        write!(w, ",&nbsp;")?
+                                        write!(w, ",&nbsp;")
                                     }
-                                    write!(w, "{}", *ty)?;
+                                    write!(w, "{}", *ty);
                                 }
-                                write!(w, ")")?;
+                                write!(w, ")");
                             }
                             clean::VariantKind::Struct(ref s) => {
                                 render_struct(w,
@@ -3524,29 +3429,29 @@
                                               s.struct_type,
                                               &s.fields,
                                               "    ",
-                                              false)?;
+                                              false);
                             }
                         }
                     }
                     _ => unreachable!()
                 }
-                write!(w, ",\n")?;
+                write!(w, ",\n");
             }
 
             if e.variants_stripped {
-                write!(w, "    // some variants omitted\n")?;
+                write!(w, "    // some variants omitted\n");
             }
-            write!(w, "}}")?;
+            write!(w, "}}");
         }
         write!(w, "</pre>")
-    })?;
+    });
 
-    document(w, cx, it)?;
+    document(w, cx, it);
     if !e.variants.is_empty() {
         write!(w, "<h2 id='variants' class='variants small-section-header'>
                    Variants{}<a href='#variants' class='anchor'></a></h2>\n",
-                   document_non_exhaustive_header(it))?;
-        document_non_exhaustive(w, it)?;
+                   document_non_exhaustive_header(it));
+        document_non_exhaustive(w, it);
         for variant in &e.variants {
             let id = cx.derive_id(format!("{}.{}",
                                        ItemType::Variant,
@@ -3554,27 +3459,27 @@
             let ns_id = cx.derive_id(format!("{}.{}",
                                           variant.name.as_ref().unwrap(),
                                           ItemType::Variant.name_space()));
-            write!(w, "<span id=\"{id}\" class=\"variant small-section-header\">\
+            write!(w, "<div id=\"{id}\" class=\"variant small-section-header\">\
                        <a href=\"#{id}\" class=\"anchor field\"></a>\
                        <code id='{ns_id}'>{name}",
                    id = id,
                    ns_id = ns_id,
-                   name = variant.name.as_ref().unwrap())?;
+                   name = variant.name.as_ref().unwrap());
             if let clean::VariantItem(ref var) = variant.inner {
                 if let clean::VariantKind::Tuple(ref tys) = var.kind {
-                    write!(w, "(")?;
+                    write!(w, "(");
                     for (i, ty) in tys.iter().enumerate() {
                         if i > 0 {
-                            write!(w, ",&nbsp;")?;
+                            write!(w, ",&nbsp;");
                         }
-                        write!(w, "{}", *ty)?;
+                        write!(w, "{}", *ty);
                     }
-                    write!(w, ")")?;
+                    write!(w, ")");
                 }
             }
-            write!(w, "</code></span>")?;
-            document(w, cx, variant)?;
-            document_non_exhaustive(w, variant)?;
+            write!(w, "</code></div>");
+            document(w, cx, variant);
+            document_non_exhaustive(w, variant);
 
             use crate::clean::{Variant, VariantKind};
             if let clean::VariantItem(Variant {
@@ -3583,10 +3488,10 @@
                 let variant_id = cx.derive_id(format!("{}.{}.fields",
                                                    ItemType::Variant,
                                                    variant.name.as_ref().unwrap()));
-                write!(w, "<span class='autohide sub-variant' id='{id}'>",
-                       id = variant_id)?;
+                write!(w, "<div class='autohide sub-variant' id='{id}'>",
+                       id = variant_id);
                 write!(w, "<h3>Fields of <b>{name}</b></h3><div>",
-                       name = variant.name.as_ref().unwrap())?;
+                       name = variant.name.as_ref().unwrap());
                 for field in &s.fields {
                     use crate::clean::StructFieldItem;
                     if let StructFieldItem(ref ty) = field.inner {
@@ -3605,17 +3510,16 @@
                                id = id,
                                ns_id = ns_id,
                                f = field.name.as_ref().unwrap(),
-                               t = *ty)?;
-                        document(w, cx, field)?;
+                               t = *ty);
+                        document(w, cx, field);
                     }
                 }
-                write!(w, "</div></span>")?;
+                write!(w, "</div></div>");
             }
-            render_stability_since(w, variant, it)?;
+            render_stability_since(w, variant, it);
         }
     }
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?;
-    Ok(())
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
 fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
@@ -3658,7 +3562,7 @@
 //     #[bar] <---- not "top" attribute
 //     bar: usize,
 // }
-fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item, top: bool) -> fmt::Result {
+fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) {
     let mut attrs = String::new();
 
     for attr in &it.attrs.other_attrs {
@@ -3671,117 +3575,114 @@
     }
     if attrs.len() > 0 {
         write!(w, "<span class=\"docblock attributes{}\">{}</span>",
-               if top { " top-attr" } else { "" }, &attrs)?;
+               if top { " top-attr" } else { "" }, &attrs);
     }
-    Ok(())
 }
 
-fn render_struct(w: &mut fmt::Formatter<'_>, it: &clean::Item,
+fn render_struct(w: &mut Buffer, it: &clean::Item,
                  g: Option<&clean::Generics>,
                  ty: doctree::StructType,
                  fields: &[clean::Item],
                  tab: &str,
-                 structhead: bool) -> fmt::Result {
+                 structhead: bool) {
     write!(w, "{}{}{}",
            VisSpace(&it.visibility),
            if structhead {"struct "} else {""},
-           it.name.as_ref().unwrap())?;
+           it.name.as_ref().unwrap());
     if let Some(g) = g {
-        write!(w, "{}", g)?
+        write!(w, "{}", g)
     }
     match ty {
         doctree::Plain => {
             if let Some(g) = g {
-                write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true })?
+                write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true })
             }
             let mut has_visible_fields = false;
-            write!(w, " {{")?;
+            write!(w, " {{");
             for field in fields {
                 if let clean::StructFieldItem(ref ty) = field.inner {
                     write!(w, "\n{}    {}{}: {},",
                            tab,
                            VisSpace(&field.visibility),
                            field.name.as_ref().unwrap(),
-                           *ty)?;
+                           *ty);
                     has_visible_fields = true;
                 }
             }
 
             if has_visible_fields {
                 if it.has_stripped_fields().unwrap() {
-                    write!(w, "\n{}    // some fields omitted", tab)?;
+                    write!(w, "\n{}    // some fields omitted", tab);
                 }
-                write!(w, "\n{}", tab)?;
+                write!(w, "\n{}", tab);
             } else if it.has_stripped_fields().unwrap() {
                 // If there are no visible fields we can just display
                 // `{ /* fields omitted */ }` to save space.
-                write!(w, " /* fields omitted */ ")?;
+                write!(w, " /* fields omitted */ ");
             }
-            write!(w, "}}")?;
+            write!(w, "}}");
         }
         doctree::Tuple => {
-            write!(w, "(")?;
+            write!(w, "(");
             for (i, field) in fields.iter().enumerate() {
                 if i > 0 {
-                    write!(w, ", ")?;
+                    write!(w, ", ");
                 }
                 match field.inner {
                     clean::StrippedItem(box clean::StructFieldItem(..)) => {
-                        write!(w, "_")?
+                        write!(w, "_")
                     }
                     clean::StructFieldItem(ref ty) => {
-                        write!(w, "{}{}", VisSpace(&field.visibility), *ty)?
+                        write!(w, "{}{}", VisSpace(&field.visibility), *ty)
                     }
                     _ => unreachable!()
                 }
             }
-            write!(w, ")")?;
+            write!(w, ")");
             if let Some(g) = g {
-                write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: false })?
+                write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: false })
             }
-            write!(w, ";")?;
+            write!(w, ";");
         }
         doctree::Unit => {
             // Needed for PhantomData.
             if let Some(g) = g {
-                write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: false })?
+                write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: false })
             }
-            write!(w, ";")?;
+            write!(w, ";");
         }
     }
-    Ok(())
 }
 
-fn render_union(w: &mut fmt::Formatter<'_>, it: &clean::Item,
+fn render_union(w: &mut Buffer, it: &clean::Item,
                 g: Option<&clean::Generics>,
                 fields: &[clean::Item],
                 tab: &str,
-                structhead: bool) -> fmt::Result {
+                structhead: bool) {
     write!(w, "{}{}{}",
            VisSpace(&it.visibility),
            if structhead {"union "} else {""},
-           it.name.as_ref().unwrap())?;
+           it.name.as_ref().unwrap());
     if let Some(g) = g {
-        write!(w, "{}", g)?;
-        write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true })?;
+        write!(w, "{}", g);
+        write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true });
     }
 
-    write!(w, " {{\n{}", tab)?;
+    write!(w, " {{\n{}", tab);
     for field in fields {
         if let clean::StructFieldItem(ref ty) = field.inner {
             write!(w, "    {}{}: {},\n{}",
                    VisSpace(&field.visibility),
                    field.name.as_ref().unwrap(),
                    *ty,
-                   tab)?;
+                   tab);
         }
     }
 
     if it.has_stripped_fields().unwrap() {
-        write!(w, "    // some fields omitted\n{}", tab)?;
+        write!(w, "    // some fields omitted\n{}", tab);
     }
-    write!(w, "}}")?;
-    Ok(())
+    write!(w, "}}");
 }
 
 #[derive(Copy, Clone)]
@@ -3810,15 +3711,15 @@
     ForDeref { mut_: bool },
 }
 
-fn render_assoc_items(w: &mut fmt::Formatter<'_>,
+fn render_assoc_items(w: &mut Buffer,
                       cx: &Context,
                       containing_item: &clean::Item,
                       it: DefId,
-                      what: AssocItemRender<'_>) -> fmt::Result {
+                      what: AssocItemRender<'_>) {
     let c = cache();
     let v = match c.impls.get(&it) {
         Some(v) => v,
-        None => return Ok(()),
+        None => return,
     };
     let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| {
         i.inner_impl().trait_.is_none()
@@ -3830,7 +3731,7 @@
                     <h2 id='methods' class='small-section-header'>\
                       Methods<a href='#methods' class='anchor'></a>\
                     </h2>\
-                ")?;
+                ");
                 RenderMode::Normal
             }
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
@@ -3839,17 +3740,17 @@
                       Methods from {}&lt;Target = {}&gt;\
                       <a href='#deref-methods' class='anchor'></a>\
                     </h2>\
-                ", trait_, type_)?;
+                ", trait_, type_);
                 RenderMode::ForDeref { mut_: deref_mut_ }
             }
         };
         for i in &non_trait {
             render_impl(w, cx, i, AssocItemLink::Anchor(None), render_mode,
-                        containing_item.stable_since(), true, None, false, true)?;
+                        containing_item.stable_since(), true, None, false, true);
         }
     }
     if let AssocItemRender::DerefFor { .. } = what {
-        return Ok(());
+        return;
     }
     if !traits.is_empty() {
         let deref_impl = traits.iter().find(|t| {
@@ -3859,31 +3760,25 @@
             let has_deref_mut = traits.iter().find(|t| {
                 t.inner_impl().trait_.def_id() == c.deref_mut_trait_did
             }).is_some();
-            render_deref_methods(w, cx, impl_, containing_item, has_deref_mut)?;
+            render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
         }
 
         let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = traits
             .iter()
             .partition(|t| t.inner_impl().synthetic);
-        let (blanket_impl, concrete) = concrete
+        let (blanket_impl, concrete): (Vec<&&Impl>, _) = concrete
             .into_iter()
             .partition(|t| t.inner_impl().blanket_impl.is_some());
 
-        struct RendererStruct<'a, 'b, 'c>(&'a Context, Vec<&'b &'b Impl>, &'c clean::Item);
-
-        impl<'a, 'b, 'c> fmt::Display for RendererStruct<'a, 'b, 'c> {
-            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-                render_impls(self.0, fmt, &self.1, self.2)
-            }
-        }
-
-        let impls = RendererStruct(cx, concrete, containing_item).to_string();
+        let mut impls = Buffer::empty_from(&w);
+        render_impls(cx, &mut impls, &concrete, containing_item);
+        let impls = impls.into_inner();
         if !impls.is_empty() {
             write!(w, "\
                 <h2 id='implementations' class='small-section-header'>\
                   Trait Implementations<a href='#implementations' class='anchor'></a>\
                 </h2>\
-                <div id='implementations-list'>{}</div>", impls)?;
+                <div id='implementations-list'>{}</div>", impls);
         }
 
         if !synthetic.is_empty() {
@@ -3893,9 +3788,9 @@
                   <a href='#synthetic-implementations' class='anchor'></a>\
                 </h2>\
                 <div id='synthetic-implementations-list'>\
-            ")?;
-            render_impls(cx, w, &synthetic, containing_item)?;
-            write!(w, "</div>")?;
+            ");
+            render_impls(cx, w, &synthetic, containing_item);
+            write!(w, "</div>");
         }
 
         if !blanket_impl.is_empty() {
@@ -3905,16 +3800,15 @@
                   <a href='#blanket-implementations' class='anchor'></a>\
                 </h2>\
                 <div id='blanket-implementations-list'>\
-            ")?;
-            render_impls(cx, w, &blanket_impl, containing_item)?;
-            write!(w, "</div>")?;
+            ");
+            render_impls(cx, w, &blanket_impl, containing_item);
+            write!(w, "</div>");
         }
     }
-    Ok(())
 }
 
-fn render_deref_methods(w: &mut fmt::Formatter<'_>, cx: &Context, impl_: &Impl,
-                        container_item: &clean::Item, deref_mut: bool) -> fmt::Result {
+fn render_deref_methods(w: &mut Buffer, cx: &Context, impl_: &Impl,
+                        container_item: &clean::Item, deref_mut: bool) {
     let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
     let target = impl_.inner_impl().items.iter().filter_map(|item| {
         match item.inner {
@@ -3929,10 +3823,9 @@
     } else {
         if let Some(prim) = target.primitive_type() {
             if let Some(&did) = cache().primitive_locations.get(&prim) {
-                render_assoc_items(w, cx, container_item, did, what)?;
+                render_assoc_items(w, cx, container_item, did, what);
             }
         }
-        Ok(())
     }
 }
 
@@ -3962,7 +3855,7 @@
     }
 }
 
-fn render_spotlight_traits(item: &clean::Item) -> Result<String, fmt::Error> {
+fn render_spotlight_traits(item: &clean::Item) -> String {
     let mut out = String::new();
 
     match item.inner {
@@ -3970,16 +3863,16 @@
         clean::TyMethodItem(clean::TyMethod { ref decl, .. }) |
         clean::MethodItem(clean::Method { ref decl, .. }) |
         clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => {
-            out = spotlight_decl(decl)?;
+            out = spotlight_decl(decl);
         }
         _ => {}
     }
 
-    Ok(out)
+    out
 }
 
-fn spotlight_decl(decl: &clean::FnDecl) -> Result<String, fmt::Error> {
-    let mut out = String::new();
+fn spotlight_decl(decl: &clean::FnDecl) -> String {
+    let mut out = Buffer::html();
     let mut trait_ = String::new();
 
     if let Some(did) = decl.output.def_id() {
@@ -4005,7 +3898,7 @@
                             assoc_type(&mut out, it, &[],
                                        Some(&tydef.type_),
                                        AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
-                                       "")?;
+                                       "");
                             out.push_str(";</span>");
                         }
                     }
@@ -4022,13 +3915,13 @@
         out.push_str("</code></div></div>");
     }
 
-    Ok(out)
+    out.into_inner()
 }
 
-fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocItemLink<'_>,
+fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>,
                render_mode: RenderMode, outer_version: Option<&str>, show_def_docs: bool,
                use_absolute: Option<bool>, is_on_foreign_type: bool,
-               show_default_items: bool) -> fmt::Result {
+               show_default_items: bool) {
     if render_mode == RenderMode::Normal {
         let id = cx.derive_id(match i.inner_impl().trait_ {
             Some(ref t) => if is_on_foreign_type {
@@ -4039,45 +3932,45 @@
             None => "impl".to_string(),
         });
         if let Some(use_absolute) = use_absolute {
-            write!(w, "<h3 id='{}' class='impl'><code class='in-band'>", id)?;
-            fmt_impl_for_trait_page(&i.inner_impl(), w, use_absolute)?;
+            write!(w, "<h3 id='{}' class='impl'><code class='in-band'>", id);
+            fmt_impl_for_trait_page(&i.inner_impl(), w, use_absolute);
             if show_def_docs {
                 for it in &i.inner_impl().items {
                     if let clean::TypedefItem(ref tydef, _) = it.inner {
-                        write!(w, "<span class=\"where fmt-newline\">  ")?;
+                        write!(w, "<span class=\"where fmt-newline\">  ");
                         assoc_type(w, it, &vec![], Some(&tydef.type_),
                                    AssocItemLink::Anchor(None),
-                                   "")?;
-                        write!(w, ";</span>")?;
+                                   "");
+                        write!(w, ";</span>");
                     }
                 }
             }
-            write!(w, "</code>")?;
+            write!(w, "</code>");
         } else {
             write!(w, "<h3 id='{}' class='impl'><code class='in-band'>{}</code>",
                 id, i.inner_impl()
-            )?;
+            );
         }
-        write!(w, "<a href='#{}' class='anchor'></a>", id)?;
+        write!(w, "<a href='#{}' class='anchor'></a>", id);
         let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
-        render_stability_since_raw(w, since, outer_version)?;
-        if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() {
+        render_stability_since_raw(w, since, outer_version);
+        if let Some(l) = cx.src_href(&i.impl_item) {
             write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
-                   l, "goto source code")?;
+                   l, "goto source code");
         }
-        write!(w, "</h3>")?;
+        write!(w, "</h3>");
         if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
             let mut ids = cx.id_map.borrow_mut();
             write!(w, "<div class='docblock'>{}</div>",
                    Markdown(&*dox, &i.impl_item.links(), &mut ids,
-                            cx.codes, cx.edition, &cx.playground).to_string())?;
+                            cx.codes, cx.edition, &cx.playground).to_string());
         }
     }
 
-    fn doc_impl_item(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item,
+    fn doc_impl_item(w: &mut Buffer, cx: &Context, item: &clean::Item,
                      link: AssocItemLink<'_>, render_mode: RenderMode,
                      is_default_item: bool, outer_version: Option<&str>,
-                     trait_: Option<&clean::Trait>, show_def_docs: bool) -> fmt::Result {
+                     trait_: Option<&clean::Trait>, show_def_docs: bool) {
         let item_type = item.type_();
         let name = item.name.as_ref().unwrap();
 
@@ -4101,50 +3994,50 @@
                 if render_method_item {
                     let id = cx.derive_id(format!("{}.{}", item_type, name));
                     let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                    write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
-                    write!(w, "{}", spotlight_decl(decl)?)?;
-                    write!(w, "<code id='{}'>", ns_id)?;
-                    render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?;
-                    write!(w, "</code>")?;
-                    render_stability_since_raw(w, item.stable_since(), outer_version)?;
-                    if let Some(l) = (Item { cx, item }).src_href() {
+                    write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
+                    write!(w, "{}", spotlight_decl(decl));
+                    write!(w, "<code id='{}'>", ns_id);
+                    render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
+                    write!(w, "</code>");
+                    render_stability_since_raw(w, item.stable_since(), outer_version);
+                    if let Some(l) = cx.src_href(item) {
                         write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
-                               l, "goto source code")?;
+                               l, "goto source code");
                     }
-                    write!(w, "</h4>")?;
+                    write!(w, "</h4>");
                 }
             }
             clean::TypedefItem(ref tydef, _) => {
                 let id = cx.derive_id(format!("{}.{}", ItemType::AssocType, name));
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
-                write!(w, "<code id='{}'>", ns_id)?;
-                assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id), "")?;
-                write!(w, "</code></h4>")?;
+                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
+                write!(w, "<code id='{}'>", ns_id);
+                assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id), "");
+                write!(w, "</code></h4>");
             }
             clean::AssocConstItem(ref ty, ref default) => {
                 let id = cx.derive_id(format!("{}.{}", item_type, name));
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
-                write!(w, "<code id='{}'>", ns_id)?;
-                assoc_const(w, item, ty, default.as_ref(), link.anchor(&id), "")?;
-                write!(w, "</code>")?;
-                render_stability_since_raw(w, item.stable_since(), outer_version)?;
-                if let Some(l) = (Item { cx, item }).src_href() {
+                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
+                write!(w, "<code id='{}'>", ns_id);
+                assoc_const(w, item, ty, default.as_ref(), link.anchor(&id), "");
+                write!(w, "</code>");
+                render_stability_since_raw(w, item.stable_since(), outer_version);
+                if let Some(l) = cx.src_href(item) {
                     write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
-                            l, "goto source code")?;
+                            l, "goto source code");
                 }
-                write!(w, "</h4>")?;
+                write!(w, "</h4>");
             }
             clean::AssocTypeItem(ref bounds, ref default) => {
                 let id = cx.derive_id(format!("{}.{}", item_type, name));
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
-                write!(w, "<code id='{}'>", ns_id)?;
-                assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id), "")?;
-                write!(w, "</code></h4>")?;
+                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
+                write!(w, "<code id='{}'>", ns_id);
+                assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id), "");
+                write!(w, "</code></h4>");
             }
-            clean::StrippedItem(..) => return Ok(()),
+            clean::StrippedItem(..) => return,
             _ => panic!("can't make docs for trait item with name {:?}", item.name)
         }
 
@@ -4156,47 +4049,46 @@
                     if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
                         // We need the stability of the item from the trait
                         // because impls can't have a stability.
-                        document_stability(w, cx, it, is_hidden)?;
+                        document_stability(w, cx, it, is_hidden);
                         if item.doc_value().is_some() {
-                            document_full(w, item, cx, "", is_hidden)?;
+                            document_full(w, item, cx, "", is_hidden);
                         } else if show_def_docs {
                             // In case the item isn't documented,
                             // provide short documentation from the trait.
-                            document_short(w, cx, it, link, "", is_hidden)?;
+                            document_short(w, cx, it, link, "", is_hidden);
                         }
                     }
                 } else {
-                    document_stability(w, cx, item, is_hidden)?;
+                    document_stability(w, cx, item, is_hidden);
                     if show_def_docs {
-                        document_full(w, item, cx, "", is_hidden)?;
+                        document_full(w, item, cx, "", is_hidden);
                     }
                 }
             } else {
-                document_stability(w, cx, item, is_hidden)?;
+                document_stability(w, cx, item, is_hidden);
                 if show_def_docs {
-                    document_short(w, cx, item, link, "", is_hidden)?;
+                    document_short(w, cx, item, link, "", is_hidden);
                 }
             }
         }
-        Ok(())
     }
 
     let traits = &cache().traits;
     let trait_ = i.trait_did().map(|did| &traits[&did]);
 
-    write!(w, "<div class='impl-items'>")?;
+    write!(w, "<div class='impl-items'>");
     for trait_item in &i.inner_impl().items {
         doc_impl_item(w, cx, trait_item, link, render_mode,
-                      false, outer_version, trait_, show_def_docs)?;
+                      false, outer_version, trait_, show_def_docs);
     }
 
-    fn render_default_items(w: &mut fmt::Formatter<'_>,
+    fn render_default_items(w: &mut Buffer,
                             cx: &Context,
                             t: &clean::Trait,
                             i: &clean::Impl,
                             render_mode: RenderMode,
                             outer_version: Option<&str>,
-                            show_def_docs: bool) -> fmt::Result {
+                            show_def_docs: bool) {
         for trait_item in &t.items {
             let n = trait_item.name.clone();
             if i.items.iter().find(|m| m.name == n).is_some() {
@@ -4206,9 +4098,8 @@
             let assoc_link = AssocItemLink::GotoSource(did, &i.provided_trait_methods);
 
             doc_impl_item(w, cx, trait_item, assoc_link, render_mode, true,
-                          outer_version, None, show_def_docs)?;
+                          outer_version, None, show_def_docs);
         }
-        Ok(())
     }
 
     // If we've implemented a trait, then also emit documentation for all
@@ -4218,29 +4109,27 @@
     if show_default_items {
         if let Some(t) = trait_ {
             render_default_items(w, cx, t, &i.inner_impl(),
-                                render_mode, outer_version, show_def_docs)?;
+                                render_mode, outer_version, show_def_docs);
         }
     }
-    write!(w, "</div>")?;
-
-    Ok(())
+    write!(w, "</div>");
 }
 
 fn item_opaque_ty(
-    w: &mut fmt::Formatter<'_>,
+    w: &mut Buffer,
     cx: &Context,
     it: &clean::Item,
     t: &clean::OpaqueTy,
-) -> fmt::Result {
-    write!(w, "<pre class='rust opaque'>")?;
-    render_attributes(w, it, false)?;
+) {
+    write!(w, "<pre class='rust opaque'>");
+    render_attributes(w, it, false);
     write!(w, "type {}{}{where_clause} = impl {bounds};</pre>",
            it.name.as_ref().unwrap(),
            t.generics,
            where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true },
-           bounds = bounds(&t.bounds, false))?;
+           bounds = bounds(&t.bounds, false));
 
-    document(w, cx, it)?;
+    document(w, cx, it);
 
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
@@ -4249,17 +4138,17 @@
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn item_trait_alias(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
-                    t: &clean::TraitAlias) -> fmt::Result {
-    write!(w, "<pre class='rust trait-alias'>")?;
-    render_attributes(w, it, false)?;
+fn item_trait_alias(w: &mut Buffer, cx: &Context, it: &clean::Item,
+                    t: &clean::TraitAlias) {
+    write!(w, "<pre class='rust trait-alias'>");
+    render_attributes(w, it, false);
     write!(w, "trait {}{}{} = {};</pre>",
            it.name.as_ref().unwrap(),
            t.generics,
            WhereClause { gens: &t.generics, indent: 0, end_newline: true },
-           bounds(&t.bounds, true))?;
+           bounds(&t.bounds, true));
 
-    document(w, cx, it)?;
+    document(w, cx, it);
 
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
@@ -4268,17 +4157,16 @@
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn item_typedef(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
-                t: &clean::Typedef) -> fmt::Result {
-    write!(w, "<pre class='rust typedef'>")?;
-    render_attributes(w, it, false)?;
+fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typedef) {
+    write!(w, "<pre class='rust typedef'>");
+    render_attributes(w, it, false);
     write!(w, "type {}{}{where_clause} = {type_};</pre>",
            it.name.as_ref().unwrap(),
            t.generics,
            where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true },
-           type_ = t.type_)?;
+           type_ = t.type_);
 
-    document(w, cx, it)?;
+    document(w, cx, it);
 
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
@@ -4287,117 +4175,111 @@
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) -> fmt::Result {
-    writeln!(w, "<pre class='rust foreigntype'>extern {{")?;
-    render_attributes(w, it, false)?;
+fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item) {
+    writeln!(w, "<pre class='rust foreigntype'>extern {{");
+    render_attributes(w, it, false);
     write!(
         w,
         "    {}type {};\n}}</pre>",
         VisSpace(&it.visibility),
         it.name.as_ref().unwrap(),
-    )?;
+    );
 
-    document(w, cx, it)?;
+    document(w, cx, it);
 
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-impl<'a> fmt::Display for Sidebar<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let cx = self.cx;
-        let it = self.item;
-        let parentlen = cx.current.len() - if it.is_mod() {1} else {0};
+fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) {
+    let parentlen = cx.current.len() - if it.is_mod() {1} else {0};
 
-        if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union()
-            || it.is_enum() || it.is_mod() || it.is_typedef() {
-            write!(fmt, "<p class='location'>{}{}</p>",
-                match it.inner {
-                    clean::StructItem(..) => "Struct ",
-                    clean::TraitItem(..) => "Trait ",
-                    clean::PrimitiveItem(..) => "Primitive Type ",
-                    clean::UnionItem(..) => "Union ",
-                    clean::EnumItem(..) => "Enum ",
-                    clean::TypedefItem(..) => "Type Definition ",
-                    clean::ForeignTypeItem => "Foreign Type ",
-                    clean::ModuleItem(..) => if it.is_crate() {
-                        "Crate "
-                    } else {
-                        "Module "
-                    },
-                    _ => "",
+    if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union()
+        || it.is_enum() || it.is_mod() || it.is_typedef() {
+        write!(buffer, "<p class='location'>{}{}</p>",
+            match it.inner {
+                clean::StructItem(..) => "Struct ",
+                clean::TraitItem(..) => "Trait ",
+                clean::PrimitiveItem(..) => "Primitive Type ",
+                clean::UnionItem(..) => "Union ",
+                clean::EnumItem(..) => "Enum ",
+                clean::TypedefItem(..) => "Type Definition ",
+                clean::ForeignTypeItem => "Foreign Type ",
+                clean::ModuleItem(..) => if it.is_crate() {
+                    "Crate "
+                } else {
+                    "Module "
                 },
-                it.name.as_ref().unwrap())?;
-        }
-
-        if it.is_crate() {
-            if let Some(ref version) = cache().crate_version {
-                write!(fmt,
-                       "<div class='block version'>\
-                        <p>Version {}</p>\
-                        </div>",
-                       version)?;
-            }
-        }
-
-        write!(fmt, "<div class=\"sidebar-elems\">")?;
-        if it.is_crate() {
-            write!(fmt, "<a id='all-types' href='all.html'><p>See all {}'s items</p></a>",
-                   it.name.as_ref().expect("crates always have a name"))?;
-        }
-        match it.inner {
-            clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?,
-            clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?,
-            clean::PrimitiveItem(ref p) => sidebar_primitive(fmt, it, p)?,
-            clean::UnionItem(ref u) => sidebar_union(fmt, it, u)?,
-            clean::EnumItem(ref e) => sidebar_enum(fmt, it, e)?,
-            clean::TypedefItem(ref t, _) => sidebar_typedef(fmt, it, t)?,
-            clean::ModuleItem(ref m) => sidebar_module(fmt, it, &m.items)?,
-            clean::ForeignTypeItem => sidebar_foreign_type(fmt, it)?,
-            _ => (),
-        }
-
-        // The sidebar is designed to display sibling functions, modules and
-        // other miscellaneous information. since there are lots of sibling
-        // items (and that causes quadratic growth in large modules),
-        // we refactor common parts into a shared JavaScript file per module.
-        // still, we don't move everything into JS because we want to preserve
-        // as much HTML as possible in order to allow non-JS-enabled browsers
-        // to navigate the documentation (though slightly inefficiently).
-
-        write!(fmt, "<p class='location'>")?;
-        for (i, name) in cx.current.iter().take(parentlen).enumerate() {
-            if i > 0 {
-                write!(fmt, "::<wbr>")?;
-            }
-            write!(fmt, "<a href='{}index.html'>{}</a>",
-                   &cx.root_path()[..(cx.current.len() - i - 1) * 3],
-                   *name)?;
-        }
-        write!(fmt, "</p>")?;
-
-        // Sidebar refers to the enclosing module, not this module.
-        let relpath = if it.is_mod() { "../" } else { "" };
-        write!(fmt,
-               "<script>window.sidebarCurrent = {{\
-                   name: '{name}', \
-                   ty: '{ty}', \
-                   relpath: '{path}'\
-                }};</script>",
-               name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""),
-               ty = it.type_().css_class(),
-               path = relpath)?;
-        if parentlen == 0 {
-            // There is no sidebar-items.js beyond the crate root path
-            // FIXME maybe dynamic crate loading can be merged here
-        } else {
-            write!(fmt, "<script defer src=\"{path}sidebar-items.js\"></script>",
-                   path = relpath)?;
-        }
-        // Closes sidebar-elems div.
-        write!(fmt, "</div>")?;
-
-        Ok(())
+                _ => "",
+            },
+            it.name.as_ref().unwrap());
     }
+
+    if it.is_crate() {
+        if let Some(ref version) = cache().crate_version {
+            write!(buffer,
+                    "<div class='block version'>\
+                    <p>Version {}</p>\
+                    </div>",
+                    version);
+        }
+    }
+
+    write!(buffer, "<div class=\"sidebar-elems\">");
+    if it.is_crate() {
+        write!(buffer, "<a id='all-types' href='all.html'><p>See all {}'s items</p></a>",
+                it.name.as_ref().expect("crates always have a name"));
+    }
+    match it.inner {
+        clean::StructItem(ref s) => sidebar_struct(buffer, it, s),
+        clean::TraitItem(ref t) => sidebar_trait(buffer, it, t),
+        clean::PrimitiveItem(ref p) => sidebar_primitive(buffer, it, p),
+        clean::UnionItem(ref u) => sidebar_union(buffer, it, u),
+        clean::EnumItem(ref e) => sidebar_enum(buffer, it, e),
+        clean::TypedefItem(ref t, _) => sidebar_typedef(buffer, it, t),
+        clean::ModuleItem(ref m) => sidebar_module(buffer, it, &m.items),
+        clean::ForeignTypeItem => sidebar_foreign_type(buffer, it),
+        _ => (),
+    }
+
+    // The sidebar is designed to display sibling functions, modules and
+    // other miscellaneous information. since there are lots of sibling
+    // items (and that causes quadratic growth in large modules),
+    // we refactor common parts into a shared JavaScript file per module.
+    // still, we don't move everything into JS because we want to preserve
+    // as much HTML as possible in order to allow non-JS-enabled browsers
+    // to navigate the documentation (though slightly inefficiently).
+
+    write!(buffer, "<p class='location'>");
+    for (i, name) in cx.current.iter().take(parentlen).enumerate() {
+        if i > 0 {
+            write!(buffer, "::<wbr>");
+        }
+        write!(buffer, "<a href='{}index.html'>{}</a>",
+                &cx.root_path()[..(cx.current.len() - i - 1) * 3],
+                *name);
+    }
+    write!(buffer, "</p>");
+
+    // Sidebar refers to the enclosing module, not this module.
+    let relpath = if it.is_mod() { "../" } else { "" };
+    write!(buffer,
+            "<script>window.sidebarCurrent = {{\
+                name: '{name}', \
+                ty: '{ty}', \
+                relpath: '{path}'\
+            }};</script>",
+            name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""),
+            ty = it.type_().css_class(),
+            path = relpath);
+    if parentlen == 0 {
+        // There is no sidebar-items.js beyond the crate root path
+        // FIXME maybe dynamic crate loading can be merged here
+    } else {
+        write!(buffer, "<script defer src=\"{path}sidebar-items.js\"></script>",
+                path = relpath);
+    }
+    // Closes sidebar-elems div.
+    write!(buffer, "</div>");
 }
 
 fn get_next_url(used_links: &mut FxHashSet<String>, url: String) -> String {
@@ -4570,8 +4452,7 @@
     out
 }
 
-fn sidebar_struct(fmt: &mut fmt::Formatter<'_>, it: &clean::Item,
-                  s: &clean::Struct) -> fmt::Result {
+fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
     let mut sidebar = String::new();
     let fields = get_struct_fields_name(&s.fields);
 
@@ -4585,9 +4466,8 @@
     sidebar.push_str(&sidebar_assoc_items(it));
 
     if !sidebar.is_empty() {
-        write!(fmt, "<div class=\"block items\">{}</div>", sidebar)?;
+        write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
-    Ok(())
 }
 
 fn get_id_for_impl_on_foreign_type(for_: &clean::Type, trait_: &clean::Type) -> String {
@@ -4611,8 +4491,7 @@
     i.polarity == Some(clean::ImplPolarity::Negative)
 }
 
-fn sidebar_trait(fmt: &mut fmt::Formatter<'_>, it: &clean::Item,
-                 t: &clean::Trait) -> fmt::Result {
+fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
     let mut sidebar = String::new();
 
     let types = t.items
@@ -4720,27 +4599,23 @@
 
     sidebar.push_str(&sidebar_assoc_items(it));
 
-    write!(fmt, "<div class=\"block items\">{}</div>", sidebar)
+    write!(buf, "<div class=\"block items\">{}</div>", sidebar)
 }
 
-fn sidebar_primitive(fmt: &mut fmt::Formatter<'_>, it: &clean::Item,
-                     _p: &clean::PrimitiveType) -> fmt::Result {
+fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item, _p: &clean::PrimitiveType) {
     let sidebar = sidebar_assoc_items(it);
 
     if !sidebar.is_empty() {
-        write!(fmt, "<div class=\"block items\">{}</div>", sidebar)?;
+        write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
-    Ok(())
 }
 
-fn sidebar_typedef(fmt: &mut fmt::Formatter<'_>, it: &clean::Item,
-                   _t: &clean::Typedef) -> fmt::Result {
+fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item, _t: &clean::Typedef) {
     let sidebar = sidebar_assoc_items(it);
 
     if !sidebar.is_empty() {
-        write!(fmt, "<div class=\"block items\">{}</div>", sidebar)?;
+        write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
-    Ok(())
 }
 
 fn get_struct_fields_name(fields: &[clean::Item]) -> String {
@@ -4758,8 +4633,7 @@
           .collect()
 }
 
-fn sidebar_union(fmt: &mut fmt::Formatter<'_>, it: &clean::Item,
-                 u: &clean::Union) -> fmt::Result {
+fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
     let mut sidebar = String::new();
     let fields = get_struct_fields_name(&u.fields);
 
@@ -4771,13 +4645,11 @@
     sidebar.push_str(&sidebar_assoc_items(it));
 
     if !sidebar.is_empty() {
-        write!(fmt, "<div class=\"block items\">{}</div>", sidebar)?;
+        write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
-    Ok(())
 }
 
-fn sidebar_enum(fmt: &mut fmt::Formatter<'_>, it: &clean::Item,
-                e: &clean::Enum) -> fmt::Result {
+fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
     let mut sidebar = String::new();
 
     let variants = e.variants.iter()
@@ -4795,9 +4667,8 @@
     sidebar.push_str(&sidebar_assoc_items(it));
 
     if !sidebar.is_empty() {
-        write!(fmt, "<div class=\"block items\">{}</div>", sidebar)?;
+        write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
-    Ok(())
 }
 
 fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) {
@@ -4831,8 +4702,7 @@
     }
 }
 
-fn sidebar_module(fmt: &mut fmt::Formatter<'_>, _it: &clean::Item,
-                  items: &[clean::Item]) -> fmt::Result {
+fn sidebar_module(buf: &mut Buffer, _it: &clean::Item, items: &[clean::Item]) {
     let mut sidebar = String::new();
 
     if items.iter().any(|it| it.type_() == ItemType::ExternCrate ||
@@ -4859,72 +4729,67 @@
     }
 
     if !sidebar.is_empty() {
-        write!(fmt, "<div class=\"block items\"><ul>{}</ul></div>", sidebar)?;
+        write!(buf, "<div class=\"block items\"><ul>{}</ul></div>", sidebar);
     }
-    Ok(())
 }
 
-fn sidebar_foreign_type(fmt: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Result {
+fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) {
     let sidebar = sidebar_assoc_items(it);
     if !sidebar.is_empty() {
-        write!(fmt, "<div class=\"block items\">{}</div>", sidebar)?;
+        write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
-    Ok(())
 }
 
-fn item_macro(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
-              t: &clean::Macro) -> fmt::Result {
+fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro) {
     wrap_into_docblock(w, |w| {
         w.write_str(&highlight::render_with_highlighting(&t.source,
                                                          Some("macro"),
                                                          None,
                                                          None))
-    })?;
+    });
     document(w, cx, it)
 }
 
-fn item_proc_macro(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, m: &clean::ProcMacro)
-    -> fmt::Result
-{
+fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::ProcMacro) {
     let name = it.name.as_ref().expect("proc-macros always have names");
     match m.kind {
         MacroKind::Bang => {
-            write!(w, "<pre class='rust macro'>")?;
-            write!(w, "{}!() {{ /* proc-macro */ }}", name)?;
-            write!(w, "</pre>")?;
+            write!(w, "<pre class='rust macro'>");
+            write!(w, "{}!() {{ /* proc-macro */ }}", name);
+            write!(w, "</pre>");
         }
         MacroKind::Attr => {
-            write!(w, "<pre class='rust attr'>")?;
-            write!(w, "#[{}]", name)?;
-            write!(w, "</pre>")?;
+            write!(w, "<pre class='rust attr'>");
+            write!(w, "#[{}]", name);
+            write!(w, "</pre>");
         }
         MacroKind::Derive => {
-            write!(w, "<pre class='rust derive'>")?;
-            write!(w, "#[derive({})]", name)?;
+            write!(w, "<pre class='rust derive'>");
+            write!(w, "#[derive({})]", name);
             if !m.helpers.is_empty() {
-                writeln!(w, "\n{{")?;
-                writeln!(w, "    // Attributes available to this derive:")?;
+                writeln!(w, "\n{{");
+                writeln!(w, "    // Attributes available to this derive:");
                 for attr in &m.helpers {
-                    writeln!(w, "    #[{}]", attr)?;
+                    writeln!(w, "    #[{}]", attr);
                 }
-                write!(w, "}}")?;
+                write!(w, "}}");
             }
-            write!(w, "</pre>")?;
+            write!(w, "</pre>");
         }
     }
     document(w, cx, it)
 }
 
-fn item_primitive(w: &mut fmt::Formatter<'_>, cx: &Context,
+fn item_primitive(w: &mut Buffer, cx: &Context,
                   it: &clean::Item,
-                  _p: &clean::PrimitiveType) -> fmt::Result {
-    document(w, cx, it)?;
+                  _p: &clean::PrimitiveType) {
+    document(w, cx, it);
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn item_keyword(w: &mut fmt::Formatter<'_>, cx: &Context,
+fn item_keyword(w: &mut Buffer, cx: &Context,
                 it: &clean::Item,
-                _p: &str) -> fmt::Result {
+                _p: &str) {
     document(w, cx, it)
 }
 
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index c1f1f59..d840683 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -4,10 +4,10 @@
 use crate::html::layout;
 use crate::html::render::{Error, SharedContext, BASIC_KEYWORDS};
 use crate::html::highlight;
+use crate::html::format::Buffer;
 use std::ffi::OsStr;
 use std::fs;
 use std::path::{Component, Path, PathBuf};
-use std::fmt;
 use syntax::source_map::FileName;
 
 crate fn render(dst: &Path, scx: &mut SharedContext,
@@ -105,7 +105,6 @@
         cur.push(&fname);
         href.push_str(&fname.to_string_lossy());
 
-        let mut v = Vec::new();
         let title = format!("{} -- source", cur.file_name().expect("failed to get file name")
                                                .to_string_lossy());
         let desc = format!("Source to the Rust file `{}`.", filename);
@@ -120,15 +119,10 @@
             extra_scripts: &[&format!("source-files{}", self.scx.resource_suffix)],
             static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)],
         };
-        let result = layout::render(&mut v, &self.scx.layout,
-                       &page, &(""), &Source(contents),
-                       self.scx.css_file_extension.is_some(),
-                       &self.scx.themes,
-                       self.scx.generate_search_filter);
-        if let Err(e) = result {
-            return Err(Error::new(e, &cur));
-        }
-        self.scx.fs.write(&cur, &v)?;
+        let v = layout::render(&self.scx.layout,
+                       &page, "", |buf: &mut _| print_src(buf, &contents),
+                       &self.scx.themes);
+        self.scx.fs.write(&cur, v.as_bytes())?;
         self.scx.local_sources.insert(p.clone(), href);
         Ok(())
     }
@@ -163,25 +157,19 @@
 
 /// Wrapper struct to render the source code of a file. This will do things like
 /// adding line numbers to the left-hand side.
-struct Source<'a>(&'a str);
-
-impl<'a> fmt::Display for Source<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Source(s) = *self;
-        let lines = s.lines().count();
-        let mut cols = 0;
-        let mut tmp = lines;
-        while tmp > 0 {
-            cols += 1;
-            tmp /= 10;
-        }
-        write!(fmt, "<pre class=\"line-numbers\">")?;
-        for i in 1..=lines {
-            write!(fmt, "<span id=\"{0}\">{0:1$}</span>\n", i, cols)?;
-        }
-        write!(fmt, "</pre>")?;
-        write!(fmt, "{}",
-               highlight::render_with_highlighting(s, None, None, None))?;
-        Ok(())
+fn print_src(buf: &mut Buffer, s: &str) {
+    let lines = s.lines().count();
+    let mut cols = 0;
+    let mut tmp = lines;
+    while tmp > 0 {
+        cols += 1;
+        tmp /= 10;
     }
+    write!(buf, "<pre class=\"line-numbers\">");
+    for i in 1..=lines {
+        write!(buf, "<span id=\"{0}\">{0:1$}</span>\n", i, cols);
+    }
+    write!(buf, "</pre>");
+    write!(buf, "{}",
+            highlight::render_with_highlighting(s, None, None, None));
 }
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 637c6ef..17a940c 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -39,6 +39,14 @@
     };
 }
 
+function getSearchInput() {
+    return document.getElementsByClassName("search-input")[0];
+}
+
+function getSearchElement() {
+    return document.getElementById("search");
+}
+
 (function() {
     "use strict";
 
@@ -71,7 +79,7 @@
                      "derive",
                      "traitalias"];
 
-    var search_input = document.getElementsByClassName("search-input")[0];
+    var search_input = getSearchInput();
 
     // On the search screen, so you remain on the last tab you opened.
     //
@@ -158,7 +166,7 @@
         // If we're in mobile mode, we should add the sidebar in any case.
         hideSidebar();
         var elem;
-        var search = document.getElementById("search");
+        var search = getSearchElement();
         var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
         if (match) {
             from = parseInt(match[1], 10);
@@ -250,7 +258,12 @@
         return String.fromCharCode(c);
     }
 
+    function getHelpElement() {
+        return document.getElementById("help");
+    }
+
     function displayHelp(display, ev, help) {
+        var help = help ? help : getHelpElement();
         if (display === true) {
             if (hasClass(help, "hidden")) {
                 ev.preventDefault();
@@ -264,9 +277,10 @@
         }
     }
 
-    function handleEscape(ev, help) {
+    function handleEscape(ev) {
+        var help = getHelpElement();
+        var search = getSearchElement();
         hideModal();
-        var search = document.getElementById("search");
         if (hasClass(help, "hidden") === false) {
             displayHelp(false, ev, help);
         } else if (hasClass(search, "hidden") === false) {
@@ -284,22 +298,21 @@
             return;
         }
 
-        var help = document.getElementById("help");
         if (document.activeElement.tagName === "INPUT") {
             switch (getVirtualKey(ev)) {
             case "Escape":
-                handleEscape(ev, help);
+                handleEscape(ev);
                 break;
             }
         } else {
             switch (getVirtualKey(ev)) {
             case "Escape":
-                handleEscape(ev, help);
+                handleEscape(ev);
                 break;
 
             case "s":
             case "S":
-                displayHelp(false, ev, help);
+                displayHelp(false, ev);
                 hideModal();
                 ev.preventDefault();
                 focusSearchBar();
@@ -314,7 +327,7 @@
             case "?":
                 if (ev.shiftKey) {
                     hideModal();
-                    displayHelp(true, ev, help);
+                    displayHelp(true, ev);
                 }
                 break;
             }
@@ -344,7 +357,7 @@
             var set_fragment = function(name) {
                 if (browserSupportsHistoryApi()) {
                     history.replaceState(null, null, "#" + name);
-                    window.hashchange();
+                    highlightSourceLines(null);
                 } else {
                     location.replace("#" + name);
                 }
@@ -547,6 +560,11 @@
                 results.sort(function(aaa, bbb) {
                     var a, b;
 
+                    // sort by exact match with regard to the last word (mismatch goes later)
+                    a = (aaa.word !== val);
+                    b = (bbb.word !== val);
+                    if (a !== b) { return a - b; }
+
                     // Sort by non levenshtein results and then levenshtein results by the distance
                     // (less changes required to match means higher rankings)
                     a = (aaa.lev);
@@ -558,11 +576,6 @@
                     b = (bbb.item.crate !== window.currentCrate);
                     if (a !== b) { return a - b; }
 
-                    // sort by exact match (mismatch goes later)
-                    a = (aaa.word !== valLower);
-                    b = (bbb.word !== valLower);
-                    if (a !== b) { return a - b; }
-
                     // sort by item name length (longer goes later)
                     a = aaa.word.length;
                     b = bbb.word.length;
@@ -1028,7 +1041,7 @@
                         if (lev > MAX_LEV_DISTANCE) {
                             continue;
                         } else if (lev > 0) {
-                            lev_add = 1;
+                            lev_add = lev / 10;
                         }
                     }
 
@@ -1099,10 +1112,6 @@
                     if (index !== -1 || lev <= MAX_LEV_DISTANCE) {
                         if (index !== -1 && paths.length < 2) {
                             lev = 0;
-                        } else if (searchWords[j] === val) {
-                            // Small trick to fix when you're looking for a one letter type
-                            // and there are other short named types.
-                            lev = -1;
                         }
                         if (results[fullId] === undefined) {
                             results[fullId] = {
@@ -1285,9 +1294,7 @@
                 } else if (e.which === 16) { // shift
                     // Does nothing, it's just to avoid losing "focus" on the highlighted element.
                 } else if (e.which === 27) { // escape
-                    removeClass(actives[currentTab][0], "highlighted");
-                    search_input.value = "";
-                    defocusSearchBar();
+                    handleEscape(e);
                 } else if (actives[currentTab].length > 0) {
                     removeClass(actives[currentTab][0], "highlighted");
                 }
@@ -1438,7 +1445,7 @@
                 ret_others[0] + ret_in_args[0] + ret_returned[0] + "</div>";
 
             addClass(main, "hidden");
-            var search = document.getElementById("search");
+            var search = getSearchElement();
             removeClass(search, "hidden");
             search.innerHTML = output;
             var tds = search.getElementsByTagName("td");
@@ -1648,7 +1655,7 @@
                     if (hasClass(main, "content")) {
                         removeClass(main, "hidden");
                     }
-                    var search_c = document.getElementById("search");
+                    var search_c = getSearchElement();
                     if (hasClass(search_c, "content")) {
                         addClass(search_c, "hidden");
                     }
@@ -1695,7 +1702,7 @@
                         if (hasClass(main, "content")) {
                             removeClass(main, "hidden");
                         }
-                        var search_c = document.getElementById("search");
+                        var search_c = getSearchElement();
                         if (hasClass(search_c, "content")) {
                             addClass(search_c, "hidden");
                         }
@@ -2464,7 +2471,7 @@
     var params = getQueryStringParams();
     if (params && params.search) {
         addClass(main, "hidden");
-        var search = document.getElementById("search");
+        var search = getSearchElement();
         removeClass(search, "hidden");
         search.innerHTML = "<h3 style=\"text-align: center;\">Loading search results...</h3>";
     }
@@ -2549,10 +2556,10 @@
 
 // Sets the focus on the search bar at the top of the page
 function focusSearchBar() {
-    document.getElementsByClassName("search-input")[0].focus();
+    getSearchInput().focus();
 }
 
 // Removes the focus from the search bar
 function defocusSearchBar() {
-    document.getElementsByClassName("search-input")[0].blur();
+    getSearchInput().blur();
 }
diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js
index 9d30e7e..eae998c 100644
--- a/src/librustdoc/html/static/storage.js
+++ b/src/librustdoc/html/static/storage.js
@@ -118,7 +118,8 @@
 }
 
 function getSystemValue() {
-    return getComputedStyle(document.documentElement).getPropertyValue('content');
+    var property = getComputedStyle(document.documentElement).getPropertyValue('content');
+    return property.replace(/[\"\']/g, "");
 }
 
 switchTheme(currentTheme, mainTheme,
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 87dac0f..0b9e717 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -1,7 +1,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
 
-#![feature(bind_by_move_pattern_guards)]
+#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))]
 #![feature(rustc_private)]
 #![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
@@ -33,6 +33,7 @@
 extern crate rustc_metadata;
 extern crate rustc_target;
 extern crate rustc_typeck;
+extern crate rustc_lexer;
 extern crate serialize;
 extern crate syntax;
 extern crate syntax_pos;
@@ -89,7 +90,7 @@
         32_000_000 // 32MB on other platforms
     };
     rustc_driver::set_sigpipe_handler();
-    env_logger::init();
+    env_logger::init_from_env("RUSTDOC_LOG");
     let res = std::thread::Builder::new().stack_size(thread_stack_size).spawn(move || {
         get_args().map(|args| main_args(&args)).unwrap_or(1)
     }).unwrap().join().unwrap_or(rustc_driver::EXIT_FAILURE);
@@ -242,9 +243,6 @@
         unstable("crate-version", |o| {
             o.optopt("", "crate-version", "crate version to print into documentation", "VERSION")
         }),
-        unstable("linker", |o| {
-            o.optopt("", "linker", "linker used for building executable test code", "PATH")
-        }),
         unstable("sort-modules-by-appearance", |o| {
             o.optflag("", "sort-modules-by-appearance", "sort modules by where they appear in the \
                                                          program, rather than alphabetically")
@@ -358,6 +356,28 @@
                       "show-coverage",
                       "calculate percentage of public items with documentation")
         }),
+        unstable("enable-per-target-ignores", |o| {
+            o.optflag("",
+                      "enable-per-target-ignores",
+                      "parse ignore-foo for ignoring doctests on a per-target basis")
+        }),
+        unstable("runtool", |o| {
+            o.optopt("",
+                     "runtool",
+                     "",
+                     "The tool to run tests with when building for a different target than host")
+        }),
+        unstable("runtool-arg", |o| {
+            o.optmulti("",
+                       "runtool-arg",
+                       "",
+                       "One (of possibly many) arguments to pass to the runtool")
+        }),
+        unstable("test-builder", |o| {
+            o.optflag("",
+                      "test-builder",
+                      "specified the rustc-like binary to use as the test builder")
+        }),
     ]
 }
 
@@ -453,7 +473,7 @@
     // First, parse the crate and extract all relevant information.
     info!("starting to run rustc");
 
-    let result = rustc_driver::report_ices_to_stderr_if_any(move || {
+    let result = rustc_driver::catch_fatal_errors(move || {
         let crate_name = options.crate_name.clone();
         let crate_version = options.crate_version.clone();
         let (mut krate, renderinfo, renderopts) = core::run_core(options);
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index a30fc05..8431271 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -43,7 +43,7 @@
     edition: Edition
 ) -> i32 {
     let mut output = options.output;
-    output.push(input.file_stem().unwrap());
+    output.push(input.file_name().unwrap());
     output.set_extension("html");
 
     let mut css = String::new();
@@ -143,11 +143,12 @@
     opts.no_crate_inject = true;
     opts.display_warnings = options.display_warnings;
     let mut collector = Collector::new(options.input.display().to_string(), options.clone(),
-                                       true, opts, None, Some(options.input));
+                                       true, opts, None, Some(options.input),
+                                       options.enable_per_target_ignores);
     collector.set_position(DUMMY_SP);
     let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
 
-    find_testable_code(&input_str, &mut collector, codes);
+    find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores);
 
     options.test_args.insert(0, "rustdoctest".to_string());
     testing::test_main(&options.test_args, collector.tests,
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 357e17d..32044e4 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -32,27 +32,39 @@
             dox[code_block.code].to_owned(),
         );
 
-        let has_errors = {
-            let mut has_errors = false;
+        let validation_status = {
+            let mut has_syntax_errors = false;
+            let mut only_whitespace = true;
+            // even if there is a syntax error, we need to run the lexer over the whole file
             let mut lexer = Lexer::new(&sess, source_file, None);
             loop  {
                 match lexer.next_token().kind {
                     token::Eof => break,
-                    token::Unknown(..) => has_errors = true,
-                    _ => (),
+                    token::Whitespace => (),
+                    token::Unknown(..) => has_syntax_errors = true,
+                    _ => only_whitespace = false,
                 }
             }
-            has_errors
+
+            if has_syntax_errors {
+                Some(CodeBlockInvalid::SyntaxError)
+            } else if only_whitespace {
+                Some(CodeBlockInvalid::Empty)
+            } else {
+                None
+            }
         };
 
-        if has_errors {
+        if let Some(code_block_invalid) = validation_status {
             let mut diag = if let Some(sp) =
                 super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs)
             {
-                let mut diag = self
-                    .cx
-                    .sess()
-                    .struct_span_warn(sp, "could not parse code block as Rust code");
+                let warning_message = match code_block_invalid {
+                    CodeBlockInvalid::SyntaxError => "could not parse code block as Rust code",
+                    CodeBlockInvalid::Empty => "Rust code block is empty",
+                };
+
+                let mut diag = self.cx.sess().struct_span_warn(sp, warning_message);
 
                 if code_block.syntax.is_none() && code_block.is_fenced {
                     let sp = sp.from_inner(InnerSpan::new(0, 3));
@@ -69,7 +81,7 @@
                 // We couldn't calculate the span of the markdown block that had the error, so our
                 // diagnostics are going to be a bit lacking.
                 let mut diag = self.cx.sess().struct_span_warn(
-                    super::span_of_attrs(&item.attrs),
+                    super::span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
                     "doc comment contains an invalid Rust code block",
                 );
 
@@ -96,3 +108,8 @@
         self.fold_item_recur(item)
     }
 }
+
+enum CodeBlockInvalid {
+    SyntaxError,
+    Empty,
+}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index c73c464..d6073cd 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -465,7 +465,7 @@
         }
     };
     let attrs = &item.attrs;
-    let sp = span_of_attrs(attrs);
+    let sp = span_of_attrs(attrs).unwrap_or(item.source.span());
 
     let mut diag = cx.tcx.struct_span_lint_hir(
         lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
@@ -517,7 +517,7 @@
         }
     };
     let attrs = &item.attrs;
-    let sp = span_of_attrs(attrs);
+    let sp = span_of_attrs(attrs).unwrap_or(item.source.span());
 
     let mut msg = format!("`{}` is ", path_str);
 
@@ -679,6 +679,7 @@
         "f32" => tcx.lang_items().f32_impl(),
         "f64" => tcx.lang_items().f64_impl(),
         "str" => tcx.lang_items().str_impl(),
+        "bool" => tcx.lang_items().bool_impl(),
         "char" => tcx.lang_items().char_impl(),
         _ => None,
     }
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 86e4e9f..28c64d0 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -53,6 +53,7 @@
         lang_items.f64_impl(),
         lang_items.f32_runtime_impl(),
         lang_items.f64_runtime_impl(),
+        lang_items.bool_impl(),
         lang_items.char_impl(),
         lang_items.str_impl(),
         lang_items.slice_impl(),
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 641a6df..14f8b16 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -336,10 +336,10 @@
         found_tests: 0,
     };
 
-    find_testable_code(&dox, &mut tests, ErrorCodes::No);
+    find_testable_code(&dox, &mut tests, ErrorCodes::No, false);
 
     if check_missing_code == true && tests.found_tests == 0 {
-        let sp = span_of_attrs(&item.attrs).substitute_dummy(item.source.span());
+        let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
         let mut diag = cx.tcx.struct_span_lint_hir(
             lint::builtin::MISSING_DOC_CODE_EXAMPLES,
             hir_id,
@@ -352,20 +352,23 @@
         let mut diag = cx.tcx.struct_span_lint_hir(
             lint::builtin::PRIVATE_DOC_TESTS,
             hir_id,
-            span_of_attrs(&item.attrs),
+            span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
             "Documentation test in private item");
         diag.emit();
     }
 }
 
 /// Returns a span encompassing all the given attributes.
-crate fn span_of_attrs(attrs: &clean::Attributes) -> Span {
+crate fn span_of_attrs(attrs: &clean::Attributes) -> Option<Span> {
     if attrs.doc_strings.is_empty() {
-        return DUMMY_SP;
+        return None;
     }
     let start = attrs.doc_strings[0].span();
+    if start == DUMMY_SP {
+        return None;
+    }
     let end = attrs.doc_strings.last().expect("No doc strings provided").span();
-    start.to(end)
+    Some(start.to(end))
 }
 
 /// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
@@ -391,7 +394,7 @@
     let snippet = cx
         .sess()
         .source_map()
-        .span_to_snippet(span_of_attrs(attrs))
+        .span_to_snippet(span_of_attrs(attrs)?)
         .ok()?;
 
     let starting_line = markdown[..md_range.start].matches('\n').count();
@@ -441,10 +444,8 @@
         }
     }
 
-    let sp = span_of_attrs(attrs).from_inner(InnerSpan::new(
+    Some(span_of_attrs(attrs)?.from_inner(InnerSpan::new(
         md_range.start + start_bytes,
         md_range.end + start_bytes + end_bytes,
-    ));
-
-    Some(sp)
+    )))
 }
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 31c0b85..482c69c 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -1,5 +1,6 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_interface::interface;
+use rustc_target::spec::TargetTriple;
 use rustc::hir;
 use rustc::hir::intravisit;
 use rustc::session::{self, config, DiagnosticOutput};
@@ -22,7 +23,7 @@
 
 use crate::clean::Attributes;
 use crate::config::Options;
-use crate::html::markdown::{self, ErrorCodes, LangString};
+use crate::html::markdown::{self, ErrorCodes, LangString, Ignore};
 
 #[derive(Clone, Default)]
 pub struct TestOptions {
@@ -57,6 +58,7 @@
             ..config::basic_debugging_options()
         },
         edition: options.edition,
+        target_triple: options.target.clone(),
         ..config::Options::default()
     };
 
@@ -82,6 +84,7 @@
 
         let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate());
         opts.display_warnings |= options.display_warnings;
+        let enable_per_target_ignores = options.enable_per_target_ignores;
         let mut collector = Collector::new(
             compiler.crate_name()?.peek().to_string(),
             options,
@@ -89,6 +92,7 @@
             opts,
             Some(compiler.source_map().clone()),
             None,
+            enable_per_target_ignores,
         );
 
         let mut global_ctxt = compiler.global_ctxt()?.take();
@@ -181,6 +185,9 @@
     should_panic: bool,
     no_run: bool,
     as_test_harness: bool,
+    runtool: Option<String>,
+    runtool_args: Vec<String>,
+    target: TargetTriple,
     compile_fail: bool,
     mut error_codes: Vec<String>,
     opts: &TestOptions,
@@ -241,7 +248,10 @@
     };
     let output_file = outdir.path().join("rust_out");
 
-    let mut compiler = Command::new(std::env::current_exe().unwrap().with_file_name("rustc"));
+    let rustc_binary = options.test_builder.as_ref().map(|v| &**v).unwrap_or_else(|| {
+        rustc_interface::util::rustc_path().expect("found rustc")
+    });
+    let mut compiler = Command::new(&rustc_binary);
     compiler.arg("--crate-type").arg("bin");
     for cfg in &options.cfgs {
         compiler.arg("--cfg").arg(&cfg);
@@ -263,15 +273,14 @@
     for extern_str in &options.extern_strs {
         compiler.arg("--extern").arg(&extern_str);
     }
+    compiler.arg("-Ccodegen-units=1");
     for codegen_options_str in &options.codegen_options_strs {
         compiler.arg("-C").arg(&codegen_options_str);
     }
-    if let Some(linker) = options.linker {
-        compiler.arg(&format!("-C linker={:?}", linker));
-    }
     if no_run {
         compiler.arg("--emit=metadata");
     }
+    compiler.arg("--target").arg(target.to_string());
 
     compiler.arg("-");
     compiler.stdin(Stdio::piped());
@@ -317,7 +326,15 @@
     }
 
     // Run the code!
-    let mut cmd = Command::new(output_file);
+    let mut cmd;
+
+    if let Some(tool) = runtool {
+        cmd = Command::new(tool);
+        cmd.arg(output_file);
+        cmd.args(runtool_args);
+    } else {
+        cmd = Command::new(output_file);
+    }
 
     match cmd.output() {
         Err(e) => return Err(TestFailure::ExecutionError(e)),
@@ -409,7 +426,7 @@
                 Ok(Some(item)) => {
                     if !found_main {
                         if let ast::ItemKind::Fn(..) = item.node {
-                            if item.ident.as_str() == "main" {
+                            if item.ident.name == sym::main {
                                 found_main = true;
                             }
                         }
@@ -605,6 +622,7 @@
 
     options: Options,
     use_headers: bool,
+    enable_per_target_ignores: bool,
     cratename: String,
     opts: TestOptions,
     position: Span,
@@ -614,12 +632,14 @@
 
 impl Collector {
     pub fn new(cratename: String, options: Options, use_headers: bool, opts: TestOptions,
-               source_map: Option<Lrc<SourceMap>>, filename: Option<PathBuf>,) -> Collector {
+               source_map: Option<Lrc<SourceMap>>, filename: Option<PathBuf>,
+               enable_per_target_ignores: bool) -> Collector {
         Collector {
             tests: Vec::new(),
             names: Vec::new(),
             options,
             use_headers,
+            enable_per_target_ignores,
             cratename,
             opts,
             position: DUMMY_SP,
@@ -663,12 +683,22 @@
         let opts = self.opts.clone();
         let edition = config.edition.unwrap_or(self.options.edition.clone());
         let options = self.options.clone();
+        let runtool = self.options.runtool.clone();
+        let runtool_args = self.options.runtool_args.clone();
+        let target = self.options.target.clone();
+        let target_str = target.to_string();
 
         debug!("creating test {}: {}", name, test);
         self.tests.push(testing::TestDescAndFn {
             desc: testing::TestDesc {
-                name: testing::DynTestName(name),
-                ignore: config.ignore,
+                name: testing::DynTestName(name.clone()),
+                ignore: match config.ignore {
+                    Ignore::All => true,
+                    Ignore::None => false,
+                    Ignore::Some(ref ignores) => {
+                        ignores.iter().any(|s| target_str.contains(s))
+                    },
+                },
                 // compiler failures are test failures
                 should_panic: testing::ShouldPanic::No,
                 allow_fail: config.allow_fail,
@@ -683,6 +713,9 @@
                     config.should_panic,
                     config.no_run,
                     config.test_harness,
+                    runtool,
+                    runtool_args,
+                    target,
                     config.compile_fail,
                     config.error_codes,
                     &opts,
@@ -765,8 +798,8 @@
             // We use these headings as test names, so it's good if
             // they're valid identifiers.
             let name = name.chars().enumerate().map(|(i, c)| {
-                    if (i == 0 && c.is_xid_start()) ||
-                        (i != 0 && c.is_xid_continue()) {
+                    if (i == 0 && rustc_lexer::is_id_start(c)) ||
+                        (i != 0 && rustc_lexer::is_id_continue(c)) {
                         c
                     } else {
                         '_'
@@ -829,7 +862,10 @@
         // anything else, this will combine them for us.
         if let Some(doc) = attrs.collapsed_doc_value() {
             self.collector.set_position(attrs.span.unwrap_or(DUMMY_SP));
-            markdown::find_testable_code(&doc, self.collector, self.codes);
+            markdown::find_testable_code(&doc,
+                                         self.collector,
+                                         self.codes,
+                                         self.collector.enable_per_target_ignores);
         }
 
         nested(self);
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 157faa0..af1d240 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -25,20 +25,14 @@
 unwind = { path = "../libunwind" }
 hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] }
 
-[dependencies.backtrace]
-version = "0.3.35"
-default-features = false # don't use coresymbolication on OSX
-features = [
-  "rustc-dep-of-std", # enable build support for integrating into libstd
-  "dbghelp",          # backtrace/symbolize on MSVC
-  "libbacktrace",     # symbolize on most platforms
-  "libunwind",        # backtrace on most platforms
-  "dladdr",           # symbolize on platforms w/o libbacktrace
-]
-optional = true
+[dependencies.backtrace_rs]
+package = "backtrace"
+version = "0.3.37"
+default-features = false # without the libstd `backtrace` feature, stub out everything
+features = [ "rustc-dep-of-std" ] # enable build support for integrating into libstd
 
 [dev-dependencies]
-rand = "0.6.1"
+rand = "0.7"
 
 [target.x86_64-apple-darwin.dependencies]
 rustc_asan = { path = "../librustc_asan" }
@@ -56,12 +50,22 @@
 [target.x86_64-fortanix-unknown-sgx.dependencies]
 fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
 
+[target.wasm32-wasi.dependencies]
+wasi = { version = "0.7.0", features = ['rustc-dep-of-std', 'alloc'] }
+
 [build-dependencies]
 cc = "1.0"
 
 [features]
 default = ["std_detect_file_io", "std_detect_dlsym_getauxval"]
 
+backtrace = [
+  "backtrace_rs/dbghelp",          # backtrace/symbolize on MSVC
+  "backtrace_rs/libbacktrace",     # symbolize on most platforms
+  "backtrace_rs/libunwind",        # backtrace on most platforms
+  "backtrace_rs/dladdr",           # symbolize on platforms w/o libbacktrace
+]
+
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
 compiler-builtins-c = ["alloc/compiler-builtins-c"]
diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs
new file mode 100644
index 0000000..61c42a5
--- /dev/null
+++ b/src/libstd/backtrace.rs
@@ -0,0 +1,353 @@
+//! Support for capturing a stack backtrace of an OS thread
+//!
+//! This module contains the support necessary to capture a stack backtrace of a
+//! running OS thread from the OS thread itself. The `Backtrace` type supports
+//! capturing a stack trace via the `Backtrace::capture` and
+//! `Backtrace::force_capture` functions.
+//!
+//! A backtrace is typically quite handy to attach to errors (e.g. types
+//! implementing `std::error::Error`) to get a causal chain of where an error
+//! was generated.
+//!
+//! > **Note**: this module is unstable and is designed in [RFC 2504], and you
+//! > can learn more about its status in the [tracking issue].
+//!
+//! [RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md
+//! [tracking issue]: https://github.com/rust-lang/rust/issues/53487
+//!
+//! ## Accuracy
+//!
+//! Backtraces are attempted to be as accurate as possible, but no guarantees
+//! are provided about the exact accuracy of a backtrace. Instruction pointers,
+//! symbol names, filenames, line numbers, etc, may all be incorrect when
+//! reported. Accuracy is attempted on a best-effort basis, however, and bugs
+//! are always welcome to indicate areas of improvement!
+//!
+//! For most platforms a backtrace with a filename/line number requires that
+//! programs be compiled with debug information. Without debug information
+//! filenames/line numbers will not be reported.
+//!
+//! ## Platform support
+//!
+//! Not all platforms that libstd compiles for support capturing backtraces.
+//! Some platforms simply do nothing when capturing a backtrace. To check
+//! whether the platform supports capturing backtraces you can consult the
+//! `BacktraceStatus` enum as a result of `Backtrace::status`.
+//!
+//! Like above with accuracy platform support is done on a best effort basis.
+//! Sometimes libraries may not be available at runtime or something may go
+//! wrong which would cause a backtrace to not be captured. Please feel free to
+//! report issues with platforms where a backtrace cannot be captured though!
+//!
+//! ## Environment Variables
+//!
+//! The `Backtrace::capture` function may not actually capture a backtrace by
+//! default. Its behavior is governed by two environment variables:
+//!
+//! * `RUST_LIB_BACKTRACE` - if this is set to `0` then `Backtrace::capture`
+//!   will never capture a backtrace. Any other value this is set to will enable
+//!   `Backtrace::capture`.
+//!
+//! * `RUST_BACKTRACE` - if `RUST_LIB_BACKTRACE` is not set, then this variable
+//!   is consulted with the same rules of `RUST_LIB_BACKTRACE`.
+//!
+//! * If neither of the above env vars are set, then `Backtrace::capture` will
+//!   be disabled.
+//!
+//! Capturing a backtrace can be a quite expensive runtime operation, so the
+//! environment variables allow either forcibly disabling this runtime
+//! performance hit or allow selectively enabling it in some programs.
+//!
+//! Note that the `Backtrace::force_capture` function can be used to ignore
+//! these environment variables. Also note that the state of environment
+//! variables is cached once the first backtrace is created, so altering
+//! `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` at runtime may not actually change
+//! how backtraces are captured.
+
+#![unstable(feature = "backtrace", issue = "53487")]
+
+// NB: A note on resolution of a backtrace:
+//
+// Backtraces primarily happen in two steps, one is where we actually capture
+// the stack backtrace, giving us a list of instruction pointers corresponding
+// to stack frames. Next we take these instruction pointers and, one-by-one,
+// turn them into a human readable name (like `main`).
+//
+// The first phase can be somewhat expensive (walking the stack), especially
+// on MSVC where debug information is consulted to return inline frames each as
+// their own frame. The second phase, however, is almost always extremely
+// expensive (on the order of milliseconds sometimes) when it's consulting debug
+// information.
+//
+// We attempt to amortize this cost as much as possible by delaying resolution
+// of an address to a human readable name for as long as possible. When
+// `Backtrace::create` is called to capture a backtrace it doesn't actually
+// perform any symbol resolution, but rather we lazily resolve symbols only just
+// before they're needed for printing. This way we can make capturing a
+// backtrace and throwing it away much cheaper, but actually printing a
+// backtrace is still basically the same cost.
+//
+// This strategy comes at the cost of some synchronization required inside of a
+// `Backtrace`, but that's a relatively small price to pay relative to capturing
+// a backtrace or actually symbolizing it.
+
+use crate::env;
+use crate::fmt;
+use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
+use crate::sync::Mutex;
+use crate::sys_common::backtrace::{output_filename, lock};
+use crate::vec::Vec;
+use backtrace_rs as backtrace;
+use backtrace::BytesOrWideString;
+
+/// A captured OS thread stack backtrace.
+///
+/// This type represents a stack backtrace for an OS thread captured at a
+/// previous point in time. In some instances the `Backtrace` type may
+/// internally be empty due to configuration. For more information see
+/// `Backtrace::capture`.
+pub struct Backtrace {
+    inner: Inner,
+}
+
+/// The current status of a backtrace, indicating whether it was captured or
+/// whether it is empty for some other reason.
+#[non_exhaustive]
+#[derive(Debug)]
+pub enum BacktraceStatus {
+    /// Capturing a backtrace is not supported, likely because it's not
+    /// implemented for the current platform.
+    Unsupported,
+    /// Capturing a backtrace has been disabled through either the
+    /// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables.
+    Disabled,
+    /// A backtrace has been captured and the `Backtrace` should print
+    /// reasonable information when rendered.
+    Captured,
+}
+
+enum Inner {
+    Unsupported,
+    Disabled,
+    Captured(Mutex<Capture>),
+}
+
+struct Capture {
+    actual_start: usize,
+    resolved: bool,
+    frames: Vec<BacktraceFrame>,
+}
+
+fn _assert_send_sync() {
+    fn _assert<T: Send + Sync>() {}
+    _assert::<Backtrace>();
+}
+
+struct BacktraceFrame {
+    frame: backtrace::Frame,
+    symbols: Vec<BacktraceSymbol>,
+}
+
+struct BacktraceSymbol {
+    name: Option<Vec<u8>>,
+    filename: Option<BytesOrWide>,
+    lineno: Option<u32>,
+}
+
+enum BytesOrWide {
+    Bytes(Vec<u8>),
+    Wide(Vec<u16>),
+}
+
+impl Backtrace {
+    /// Returns whether backtrace captures are enabled through environment
+    /// variables.
+    fn enabled() -> bool {
+        // Cache the result of reading the environment variables to make
+        // backtrace captures speedy, because otherwise reading environment
+        // variables every time can be somewhat slow.
+        static ENABLED: AtomicUsize = AtomicUsize::new(0);
+        match ENABLED.load(SeqCst) {
+            0 => {}
+            1 => return false,
+            _ => return true,
+        }
+        let enabled = match env::var("RUST_LIB_BACKTRACE") {
+            Ok(s) => s != "0",
+            Err(_) => match env::var("RUST_BACKTRACE") {
+                Ok(s) => s != "0",
+                Err(_) => false,
+            },
+        };
+        ENABLED.store(enabled as usize + 1, SeqCst);
+        return enabled;
+    }
+
+    /// Capture a stack backtrace of the current thread.
+    ///
+    /// This function will capture a stack backtrace of the current OS thread of
+    /// execution, returning a `Backtrace` type which can be later used to print
+    /// the entire stack trace or render it to a string.
+    ///
+    /// This function will be a noop if the `RUST_BACKTRACE` or
+    /// `RUST_LIB_BACKTRACE` backtrace variables are both not set. If either
+    /// environment variable is set and enabled then this function will actually
+    /// capture a backtrace. Capturing a backtrace can be both memory intensive
+    /// and slow, so these environment variables allow liberally using
+    /// `Backtrace::capture` and only incurring a slowdown when the environment
+    /// variables are set.
+    ///
+    /// To forcibly capture a backtrace regardless of environment variables, use
+    /// the `Backtrace::force_capture` function.
+    #[inline(never)] // want to make sure there's a frame here to remove
+    pub fn capture() -> Backtrace {
+        if !Backtrace::enabled() {
+            return Backtrace { inner: Inner::Disabled };
+        }
+        Backtrace::create(Backtrace::capture as usize)
+    }
+
+    /// Forcibly captures a full backtrace, regardless of environment variable
+    /// configuration.
+    ///
+    /// This function behaves the same as `capture` except that it ignores the
+    /// values of the `RUST_BACKTRACE` and `RUST_LIB_BACKTRACE` environment
+    /// variables, always capturing a backtrace.
+    ///
+    /// Note that capturing a backtrace can be an expensive operation on some
+    /// platforms, so this should be used with caution in performance-sensitive
+    /// parts of code.
+    #[inline(never)] // want to make sure there's a frame here to remove
+    pub fn force_capture() -> Backtrace {
+        Backtrace::create(Backtrace::force_capture as usize)
+    }
+
+    // Capture a backtrace which start just before the function addressed by
+    // `ip`
+    fn create(ip: usize) -> Backtrace {
+        let _lock = lock();
+        let mut frames = Vec::new();
+        let mut actual_start = None;
+        unsafe {
+            backtrace::trace_unsynchronized(|frame| {
+                frames.push(BacktraceFrame { frame: frame.clone(), symbols: Vec::new() });
+                if frame.symbol_address() as usize == ip && actual_start.is_none() {
+                    actual_start = Some(frames.len());
+                }
+                true
+            });
+        }
+
+        // If no frames came out assume that this is an unsupported platform
+        // since `backtrace` doesn't provide a way of learning this right now,
+        // and this should be a good enough approximation.
+        let inner = if frames.len() == 0 {
+            Inner::Unsupported
+        } else {
+            Inner::Captured(Mutex::new(Capture {
+                actual_start: actual_start.unwrap_or(0),
+                frames,
+                resolved: false,
+            }))
+        };
+
+        Backtrace { inner }
+    }
+
+    /// Returns the status of this backtrace, indicating whether this backtrace
+    /// request was unsupported, disabled, or a stack trace was actually
+    /// captured.
+    pub fn status(&self) -> BacktraceStatus {
+        match self.inner {
+            Inner::Unsupported => BacktraceStatus::Unsupported,
+            Inner::Disabled => BacktraceStatus::Disabled,
+            Inner::Captured(_) => BacktraceStatus::Captured,
+        }
+    }
+}
+
+impl fmt::Display for Backtrace {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(self, fmt)
+    }
+}
+
+impl fmt::Debug for Backtrace {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut capture = match &self.inner {
+            Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
+            Inner::Disabled => return fmt.write_str("disabled backtrace"),
+            Inner::Captured(c) => c.lock().unwrap(),
+        };
+        capture.resolve();
+
+        let full = fmt.alternate();
+        let (frames, style) = if full {
+            (&capture.frames[..], backtrace::PrintFmt::Full)
+        } else {
+            (&capture.frames[capture.actual_start..], backtrace::PrintFmt::Short)
+        };
+
+        // When printing paths we try to strip the cwd if it exists, otherwise
+        // we just print the path as-is. Note that we also only do this for the
+        // short format, because if it's full we presumably want to print
+        // everything.
+        let cwd = crate::env::current_dir();
+        let mut print_path = move |fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>| {
+            output_filename(fmt, path, style, cwd.as_ref().ok())
+        };
+
+        let mut f = backtrace::BacktraceFmt::new(fmt, style, &mut print_path);
+        f.add_context()?;
+        for frame in frames {
+            let mut f = f.frame();
+            if frame.symbols.is_empty() {
+                f.print_raw(frame.frame.ip(), None, None, None)?;
+            } else {
+                for symbol in frame.symbols.iter() {
+                    f.print_raw(
+                        frame.frame.ip(),
+                        symbol.name.as_ref().map(|b| backtrace::SymbolName::new(b)),
+                        symbol.filename.as_ref().map(|b| match b {
+                            BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
+                            BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
+                        }),
+                        symbol.lineno,
+                    )?;
+                }
+            }
+        }
+        f.finish()?;
+        Ok(())
+    }
+}
+
+impl Capture {
+    fn resolve(&mut self) {
+        // If we're already resolved, nothing to do!
+        if self.resolved {
+            return;
+        }
+        self.resolved = true;
+
+        // Use the global backtrace lock to synchronize this as it's a
+        // requirement of the `backtrace` crate, and then actually resolve
+        // everything.
+        let _lock = lock();
+        for frame in self.frames.iter_mut() {
+            let symbols = &mut frame.symbols;
+            unsafe {
+                backtrace::resolve_frame_unsynchronized(&frame.frame, |symbol| {
+                    symbols.push(BacktraceSymbol {
+                        name: symbol.name().map(|m| m.as_bytes().to_vec()),
+                        filename: symbol.filename_raw().map(|b| match b {
+                            BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()),
+                            BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
+                        }),
+                        lineno: symbol.lineno(),
+                    });
+                });
+            }
+        }
+    }
+}
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index eca9339..b898936 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -290,7 +290,7 @@
 ///
 /// Note that while concurrent access to environment variables is safe in Rust,
 /// some platforms only expose inherently unsafe non-threadsafe APIs for
-/// inspecting the environment. As a result extra care needs to be taken when
+/// inspecting the environment. As a result, extra care needs to be taken when
 /// auditing calls to unsafe external FFI functions to ensure that any external
 /// environment accesses are properly synchronized with accesses in Rust.
 ///
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 117a430..4a1bb75 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -17,6 +17,7 @@
 
 use crate::alloc::{AllocErr, LayoutErr, CannotReallocInPlace};
 use crate::any::TypeId;
+use crate::backtrace::Backtrace;
 use crate::borrow::Cow;
 use crate::cell;
 use crate::char;
@@ -196,14 +197,28 @@
     #[stable(feature = "error_source", since = "1.30.0")]
     fn source(&self) -> Option<&(dyn Error + 'static)> { None }
 
-    /// Gets the `TypeId` of `self`
+    /// Gets the `TypeId` of `self`.
     #[doc(hidden)]
     #[unstable(feature = "error_type_id",
-               reason = "this is memory unsafe to override in user code",
+               reason = "this is memory-unsafe to override in user code",
                issue = "60784")]
     fn type_id(&self, _: private::Internal) -> TypeId where Self: 'static {
         TypeId::of::<Self>()
     }
+
+    /// Returns a stack backtrace, if available, of where this error ocurred.
+    ///
+    /// This function allows inspecting the location, in code, of where an error
+    /// happened. The returned `Backtrace` contains information about the stack
+    /// trace of the OS thread of execution of where the error originated from.
+    ///
+    /// Note that not all errors contain a `Backtrace`. Also note that a
+    /// `Backtrace` may actually be empty. For more information consult the
+    /// `Backtrace` type itself.
+    #[unstable(feature = "backtrace", issue = "53487")]
+    fn backtrace(&self) -> Option<&Backtrace> {
+        None
+    }
 }
 
 mod private {
@@ -601,19 +616,19 @@
     }
 }
 
-// copied from any.rs
+// Copied from `any.rs`.
 impl dyn Error + 'static {
     /// Returns `true` if the boxed type is the same as `T`
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn is<T: Error + 'static>(&self) -> bool {
-        // Get TypeId of the type this function is instantiated with
+        // Get `TypeId` of the type this function is instantiated with.
         let t = TypeId::of::<T>();
 
-        // Get TypeId of the type in the trait object
+        // Get `TypeId` of the type in the trait object.
         let boxed = self.type_id(private::Internal);
 
-        // Compare both TypeIds on equality
+        // Compare both `TypeId`s on equality.
         t == boxed
     }
 
@@ -647,21 +662,21 @@
 }
 
 impl dyn Error + 'static + Send {
-    /// Forwards to the method defined on the type `Any`.
+    /// Forwards to the method defined on the type `dyn Error`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn is<T: Error + 'static>(&self) -> bool {
         <dyn Error + 'static>::is::<T>(self)
     }
 
-    /// Forwards to the method defined on the type `Any`.
+    /// Forwards to the method defined on the type `dyn Error`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
         <dyn Error + 'static>::downcast_ref::<T>(self)
     }
 
-    /// Forwards to the method defined on the type `Any`.
+    /// Forwards to the method defined on the type `dyn Error`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
@@ -670,21 +685,21 @@
 }
 
 impl dyn Error + 'static + Send + Sync {
-    /// Forwards to the method defined on the type `Any`.
+    /// Forwards to the method defined on the type `dyn Error`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn is<T: Error + 'static>(&self) -> bool {
         <dyn Error + 'static>::is::<T>(self)
     }
 
-    /// Forwards to the method defined on the type `Any`.
+    /// Forwards to the method defined on the type `dyn Error`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
         <dyn Error + 'static>::downcast_ref::<T>(self)
     }
 
-    /// Forwards to the method defined on the type `Any`.
+    /// Forwards to the method defined on the type `dyn Error`.
     #[stable(feature = "error_downcast", since = "1.3.0")]
     #[inline]
     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
@@ -695,7 +710,7 @@
 impl dyn Error {
     #[inline]
     #[stable(feature = "error_downcast", since = "1.3.0")]
-    /// Attempt to downcast the box to a concrete type.
+    /// Attempts to downcast the box to a concrete type.
     pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
         if self.is::<T>() {
             unsafe {
@@ -863,12 +878,12 @@
 impl dyn Error + Send {
     #[inline]
     #[stable(feature = "error_downcast", since = "1.3.0")]
-    /// Attempt to downcast the box to a concrete type.
+    /// Attempts to downcast the box to a concrete type.
     pub fn downcast<T: Error + 'static>(self: Box<Self>)
                                         -> Result<Box<T>, Box<dyn Error + Send>> {
         let err: Box<dyn Error> = self;
         <dyn Error>::downcast(err).map_err(|s| unsafe {
-            // reapply the Send marker
+            // Reapply the `Send` marker.
             transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
         })
     }
@@ -877,12 +892,12 @@
 impl dyn Error + Send + Sync {
     #[inline]
     #[stable(feature = "error_downcast", since = "1.3.0")]
-    /// Attempt to downcast the box to a concrete type.
+    /// Attempts to downcast the box to a concrete type.
     pub fn downcast<T: Error + 'static>(self: Box<Self>)
                                         -> Result<Box<T>, Box<Self>> {
         let err: Box<dyn Error> = self;
         <dyn Error>::downcast(err).map_err(|s| unsafe {
-            // reapply the Send+Sync marker
+            // Reapply the `Send + Sync` marker.
             transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
         })
     }
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 65f4e0c..d7f4cc5 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -615,7 +615,7 @@
 }
 
 // Turns this `CString` into an empty string to prevent
-// memory unsafe code from working by accident. Inline
+// memory-unsafe code from working by accident. Inline
 // to prevent LLVM from optimizing it away in debug builds.
 #[stable(feature = "cstring_drop", since = "1.13.0")]
 impl Drop for CString {
@@ -935,8 +935,10 @@
     /// Wraps a raw C string with a safe C string wrapper.
     ///
     /// This function will wrap the provided `ptr` with a `CStr` wrapper, which
-    /// allows inspection and interoperation of non-owned C strings. This method
-    /// is unsafe for a number of reasons:
+    /// allows inspection and interoperation of non-owned C strings. The total
+    /// size of the raw C string must be smaller than `isize::MAX` **bytes**
+    /// in memory due to calling the `slice::from_raw_parts` function.
+    /// This method is unsafe for a number of reasons:
     ///
     /// * There is no guarantee to the validity of `ptr`.
     /// * The returned lifetime is not guaranteed to be the actual lifetime of
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 5f76875..b5265fe 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1956,7 +1956,8 @@
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `opendir` function on Unix
-/// and the `FindFirstFile` function on Windows.
+/// and the `FindFirstFile` function on Windows. Advancing the iterator
+/// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: ../io/index.html#platform-specific-behavior
@@ -2144,7 +2145,7 @@
     use crate::sys_common::io::test::{TempDir, tmpdir};
     use crate::thread;
 
-    use rand::{rngs::StdRng, FromEntropy, RngCore};
+    use rand::{rngs::StdRng, RngCore, SeedableRng};
 
     #[cfg(windows)]
     use crate::os::windows::fs::{symlink_dir, symlink_file};
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index aaf628e..9593a1b 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -9,21 +9,21 @@
         IoSliceMut};
 use crate::memchr;
 
-/// The `BufReader` struct adds buffering to any reader.
+/// The `BufReader<R>` struct adds buffering to any reader.
 ///
 /// It can be excessively inefficient to work directly with a [`Read`] instance.
 /// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`]
-/// results in a system call. A `BufReader` performs large, infrequent reads on
+/// results in a system call. A `BufReader<R>` performs large, infrequent reads on
 /// the underlying [`Read`] and maintains an in-memory buffer of the results.
 ///
-/// `BufReader` can improve the speed of programs that make *small* and
+/// `BufReader<R>` can improve the speed of programs that make *small* and
 /// *repeated* read calls to the same file or network socket. It does not
 /// help when reading very large amounts at once, or reading just one or a few
 /// times. It also provides no advantage when reading from a source that is
 /// already in memory, like a `Vec<u8>`.
 ///
-/// When the `BufReader` is dropped, the contents of its buffer will be
-/// discarded. Creating multiple instances of a `BufReader` on the same
+/// When the `BufReader<R>` is dropped, the contents of its buffer will be
+/// discarded. Creating multiple instances of a `BufReader<R>` on the same
 /// stream can cause data loss.
 ///
 /// [`Read`]: ../../std/io/trait.Read.html
@@ -56,7 +56,7 @@
 }
 
 impl<R: Read> BufReader<R> {
-    /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB,
+    /// Creates a new `BufReader<R>` with a default buffer capacity. The default is currently 8 KB,
     /// but may change in the future.
     ///
     /// # Examples
@@ -76,7 +76,7 @@
         BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
     }
 
-    /// Creates a new `BufReader` with the specified buffer capacity.
+    /// Creates a new `BufReader<R>` with the specified buffer capacity.
     ///
     /// # Examples
     ///
@@ -177,7 +177,7 @@
         &self.buf[self.pos..self.cap]
     }
 
-    /// Unwraps this `BufReader`, returning the underlying reader.
+    /// Unwraps this `BufReader<R>`, returning the underlying reader.
     ///
     /// Note that any leftover data in the internal buffer is lost.
     ///
@@ -304,7 +304,7 @@
     /// Seek to an offset, in bytes, in the underlying reader.
     ///
     /// The position used for seeking with `SeekFrom::Current(_)` is the
-    /// position the underlying reader would be at if the `BufReader` had no
+    /// position the underlying reader would be at if the `BufReader<R>` had no
     /// internal buffer.
     ///
     /// Seeking always discards the internal buffer, even if the seek position
@@ -355,19 +355,20 @@
 /// It can be excessively inefficient to work directly with something that
 /// implements [`Write`]. For example, every call to
 /// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A
-/// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying
+/// `BufWriter<W>` keeps an in-memory buffer of data and writes it to an underlying
 /// writer in large, infrequent batches.
 ///
-/// `BufWriter` can improve the speed of programs that make *small* and
+/// `BufWriter<W>` can improve the speed of programs that make *small* and
 /// *repeated* write calls to the same file or network socket. It does not
 /// help when writing very large amounts at once, or writing just one or a few
 /// times. It also provides no advantage when writing to a destination that is
 /// in memory, like a `Vec<u8>`.
 ///
-/// When the `BufWriter` is dropped, the contents of its buffer will be written
-/// out. However, any errors that happen in the process of flushing the buffer
-/// when the writer is dropped will be ignored. Code that wishes to handle such
-/// errors must manually call [`flush`] before the writer is dropped.
+/// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
+/// dropping will attempt to flush the the contents of the buffer, any errors
+/// that happen in the process of dropping will be ignored. Calling ['flush']
+/// ensures that the buffer is empty and thus dropping will not even attempt
+/// file operations.
 ///
 /// # Examples
 ///
@@ -386,7 +387,7 @@
 ///
 /// Because we're not buffering, we write each one in turn, incurring the
 /// overhead of a system call per byte written. We can fix this with a
-/// `BufWriter`:
+/// `BufWriter<W>`:
 ///
 /// ```no_run
 /// use std::io::prelude::*;
@@ -398,11 +399,12 @@
 /// for i in 0..10 {
 ///     stream.write(&[i+1]).unwrap();
 /// }
+/// stream.flush().unwrap();
 /// ```
 ///
-/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped
-/// together by the buffer, and will all be written out in one system call when
-/// the `stream` is dropped.
+/// By wrapping the stream with a `BufWriter<W>`, these ten writes are all grouped
+/// together by the buffer and will all be written out in one system call when
+/// the `stream` is flushed.
 ///
 /// [`Write`]: ../../std/io/trait.Write.html
 /// [`TcpStream::write`]: ../../std/net/struct.TcpStream.html#method.write
@@ -447,7 +449,7 @@
 pub struct IntoInnerError<W>(W, Error);
 
 impl<W: Write> BufWriter<W> {
-    /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB,
+    /// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KB,
     /// but may change in the future.
     ///
     /// # Examples
@@ -463,7 +465,7 @@
         BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
     }
 
-    /// Creates a new `BufWriter` with the specified buffer capacity.
+    /// Creates a new `BufWriter<W>` with the specified buffer capacity.
     ///
     /// # Examples
     ///
@@ -564,7 +566,7 @@
         &self.buf
     }
 
-    /// Unwraps this `BufWriter`, returning the underlying writer.
+    /// Unwraps this `BufWriter<W>`, returning the underlying writer.
     ///
     /// The buffer is written out before returning the writer.
     ///
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 5060f36..be364a1 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -371,6 +371,14 @@
     loop {
         if g.len == g.buf.len() {
             unsafe {
+                // FIXME(danielhenrymantilla): #42788
+                //
+                //   - This creates a (mut) reference to a slice of
+                //     _uninitialized_ integers, which is **undefined behavior**
+                //
+                //   - Only the standard library gets to soundly "ignore" this,
+                //     based on its privileged knowledge of unstable rustc
+                //     internals;
                 g.buf.reserve(reservation_size(r));
                 let capacity = g.buf.capacity();
                 g.buf.set_len(capacity);
@@ -2318,10 +2326,10 @@
 /// An iterator over the contents of an instance of `BufRead` split on a
 /// particular byte.
 ///
-/// This struct is generally created by calling [`split`][split] on a
-/// `BufRead`. Please see the documentation of `split()` for more details.
+/// This struct is generally created by calling [`split`] on a `BufRead`.
+/// Please see the documentation of [`split`] for more details.
 ///
-/// [split]: trait.BufRead.html#method.split
+/// [`split`]: trait.BufRead.html#method.split
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Split<B> {
@@ -2350,10 +2358,10 @@
 
 /// An iterator over the lines of an instance of `BufRead`.
 ///
-/// This struct is generally created by calling [`lines`][lines] on a
-/// `BufRead`. Please see the documentation of `lines()` for more details.
+/// This struct is generally created by calling [`lines`] on a `BufRead`.
+/// Please see the documentation of [`lines`] for more details.
 ///
-/// [lines]: trait.BufRead.html#method.lines
+/// [`lines`]: trait.BufRead.html#method.lines
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Lines<B> {
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 990c0eb..c798ee0 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -201,9 +201,9 @@
 ///
 /// Each handle returned is a reference to a shared global buffer whose access
 /// is synchronized via a mutex. If you need more explicit control over
-/// locking, see the [`lock() method`][lock].
+/// locking, see the [`Stdin::lock`] method.
 ///
-/// [lock]: struct.Stdin.html#method.lock
+/// [`Stdin::lock`]: struct.Stdin.html#method.lock
 ///
 /// ### Note: Windows Portability Consideration
 /// When operating in a console, the Windows implementation of this stream does not support
@@ -425,9 +425,9 @@
 ///
 /// Each handle returned is a reference to a shared global buffer whose access
 /// is synchronized via a mutex. If you need more explicit control over
-/// locking, see the [Stdout::lock] method.
+/// locking, see the [`Stdout::lock`] method.
 ///
-/// [Stdout::lock]: struct.Stdout.html#method.lock
+/// [`Stdout::lock`]: struct.Stdout.html#method.lock
 ///
 /// ### Note: Windows Portability Consideration
 /// When operating in a console, the Windows implementation of this stream does not support
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index 85a9dea..a8dfe92 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -681,14 +681,15 @@
 ///     # break;
 /// }
 ///
-/// let mut i = 0;
+/// let mut i = 1;
 /// loop {
 ///     println!("i is {}", i);
-///     if i > 10 {
+///     if i > 100 {
 ///         break;
 ///     }
-///     i += 1;
+///     i *= 2;
 /// }
+/// assert_eq!(i, 128);
 /// ```
 ///
 /// Unlike the other kinds of loops in Rust (`while`, `while let`, and `for`), loops can be used as
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index c3882ba..21aeb9c 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -238,13 +238,12 @@
 #![feature(array_error_internals)]
 #![feature(asm)]
 #![feature(associated_type_bounds)]
-#![feature(bind_by_move_pattern_guards)]
+#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
 #![feature(cfg_target_has_atomic)]
 #![feature(cfg_target_thread_local)]
 #![feature(char_error_internals)]
-#![feature(checked_duration_since)]
 #![feature(clamp)]
 #![feature(compiler_builtins_lib)]
 #![feature(concat_idents)]
@@ -453,6 +452,7 @@
 #[macro_use]
 pub mod thread;
 pub mod ascii;
+pub mod backtrace;
 pub mod collections;
 pub mod env;
 pub mod error;
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index cdffa39..d8b6fb6 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -1597,7 +1597,8 @@
 
     // FIXME: re-enabled openbsd tests once their socket timeout code
     //        no longer has rounding errors.
-    #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd"), ignore)]
+    // VxWorks ignores SO_SNDTIMEO.
+    #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
     #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     #[test]
     fn timeouts() {
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index c430e10..a5e7cd9 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -1026,7 +1026,8 @@
 
     // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code
     //        no longer has rounding errors.
-    #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd"), ignore)]
+    // VxWorks ignores SO_SNDTIMEO.
+    #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
     #[test]
     fn timeouts() {
         let addr = next_test_ip4();
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 952fd9e..28fb402 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -17,8 +17,7 @@
 use crate::raw;
 use crate::sys::stdio::panic_output;
 use crate::sys_common::rwlock::RWLock;
-use crate::sys_common::thread_info;
-use crate::sys_common::util;
+use crate::sys_common::{thread_info, util, backtrace};
 use crate::thread;
 
 #[cfg(not(test))]
@@ -157,20 +156,18 @@
 }
 
 fn default_hook(info: &PanicInfo<'_>) {
-    #[cfg(feature = "backtrace")]
-    use crate::sys_common::backtrace;
-
     // If this is a double panic, make sure that we print a backtrace
     // for this panic. Otherwise only print it if logging is enabled.
-    #[cfg(feature = "backtrace")]
-    let log_backtrace = {
+    let log_backtrace = if cfg!(feature = "backtrace") {
         let panics = update_panic_count(0);
 
         if panics >= 2 {
-            Some(backtrace::PrintFormat::Full)
+            Some(backtrace_rs::PrintFmt::Full)
         } else {
             backtrace::log_enabled()
         }
+    } else {
+        None
     };
 
     // The current implementation always returns `Some`.
@@ -190,8 +187,7 @@
         let _ = writeln!(err, "thread '{}' panicked at '{}', {}",
                          name, msg, location);
 
-        #[cfg(feature = "backtrace")]
-        {
+        if cfg!(feature = "backtrace") {
             use crate::sync::atomic::{AtomicBool, Ordering};
 
             static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 000f80f..b8d57cf 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -422,7 +422,7 @@
 /// // Execute `ls` in the current directory of the program.
 /// list_dir.status().expect("process failed to execute");
 ///
-/// println!("");
+/// println!();
 ///
 /// // Change `ls` to execute in the root directory.
 /// list_dir.current_dir("/");
@@ -1595,7 +1595,7 @@
 
 /// A trait for implementing arbitrary return types in the `main` function.
 ///
-/// The c-main function only supports to return integers as return type.
+/// The C-main function only supports to return integers as return type.
 /// So, every type implementing the `Termination` trait has to be converted
 /// to an integer.
 ///
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index aeff577..65ce19f 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -28,14 +28,14 @@
     /// once the boolean has been updated and notified.
     ///
     /// ```
-    /// use std::sync::{Arc, Mutex, Condvar};
+    /// use std::sync::{Arc, Condvar, Mutex};
     /// use std::thread;
     /// use std::time::Duration;
     ///
     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
     /// let pair2 = pair.clone();
     ///
-    /// thread::spawn(move|| {
+    /// thread::spawn(move || {
     ///     let (lock, cvar) = &*pair2;
     ///
     ///     // Let's wait 20 milliseconds before notifying the condvar.
diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs
index e719b36..03a59d6 100644
--- a/src/libstd/sys/cloudabi/shims/process.rs
+++ b/src/libstd/sys/cloudabi/shims/process.rs
@@ -4,14 +4,16 @@
 use crate::sys::fs::File;
 use crate::sys::pipe::AnonPipe;
 use crate::sys::{unsupported, Void};
-use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::sys_common::process::CommandEnv;
+
+pub use crate::ffi::OsString as EnvKey;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct Command {
-    env: CommandEnv<DefaultEnvKey>,
+    env: CommandEnv,
 }
 
 // passed back to std::process with the pipes connected to the child, if any
@@ -37,7 +39,7 @@
 
     pub fn arg(&mut self, _arg: &OsStr) {}
 
-    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+    pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
     }
 
diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs
index 000bb19..cc1c04a 100644
--- a/src/libstd/sys/sgx/condvar.rs
+++ b/src/libstd/sys/sgx/condvar.rs
@@ -27,8 +27,7 @@
 
     pub unsafe fn wait(&self, mutex: &Mutex) {
         let guard = self.inner.lock();
-        mutex.unlock();
-        WaitQueue::wait(guard);
+        WaitQueue::wait(guard, || mutex.unlock());
         mutex.lock()
     }
 
diff --git a/src/libstd/sys/sgx/mutex.rs b/src/libstd/sys/sgx/mutex.rs
index f325fb1..662da8b 100644
--- a/src/libstd/sys/sgx/mutex.rs
+++ b/src/libstd/sys/sgx/mutex.rs
@@ -22,7 +22,7 @@
         let mut guard = self.inner.lock();
         if *guard.lock_var() {
             // Another thread has the lock, wait
-            WaitQueue::wait(guard)
+            WaitQueue::wait(guard, ||{})
             // Another thread has passed the lock to us
         } else {
             // We are just now obtaining the lock
@@ -83,7 +83,7 @@
         match guard.lock_var().owner {
             Some(tcs) if tcs != thread::current() => {
                 // Another thread has the lock, wait
-                WaitQueue::wait(guard);
+                WaitQueue::wait(guard, ||{});
                 // Another thread has passed the lock to us
             },
             _ => {
diff --git a/src/libstd/sys/sgx/process.rs b/src/libstd/sys/sgx/process.rs
index a02e009..edf933d 100644
--- a/src/libstd/sys/sgx/process.rs
+++ b/src/libstd/sys/sgx/process.rs
@@ -4,14 +4,16 @@
 use crate::sys::fs::File;
 use crate::sys::pipe::AnonPipe;
 use crate::sys::{unsupported, Void};
-use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::sys_common::process::CommandEnv;
+
+pub use crate::ffi::OsString as EnvKey;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct Command {
-    env: CommandEnv<DefaultEnvKey>
+    env: CommandEnv,
 }
 
 // passed back to std::process with the pipes connected to the child, if any
@@ -38,7 +40,7 @@
     pub fn arg(&mut self, _arg: &OsStr) {
     }
 
-    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+    pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
     }
 
diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs
index 30c47e4..e2f94b1 100644
--- a/src/libstd/sys/sgx/rwlock.rs
+++ b/src/libstd/sys/sgx/rwlock.rs
@@ -31,7 +31,7 @@
         if *wguard.lock_var() || !wguard.queue_empty() {
             // Another thread has or is waiting for the write lock, wait
             drop(wguard);
-            WaitQueue::wait(rguard);
+            WaitQueue::wait(rguard, ||{});
             // Another thread has passed the lock to us
         } else {
             // No waiting writers, acquire the read lock
@@ -62,7 +62,7 @@
         if *wguard.lock_var() || rguard.lock_var().is_some() {
             // Another thread has the lock, wait
             drop(rguard);
-            WaitQueue::wait(wguard);
+            WaitQueue::wait(wguard, ||{});
             // Another thread has passed the lock to us
         } else {
             // We are just now obtaining the lock
@@ -97,6 +97,7 @@
             if let Ok(mut wguard) = WaitQueue::notify_one(wguard) {
                 // A writer was waiting, pass the lock
                 *wguard.lock_var_mut() = true;
+                wguard.drop_after(rguard);
             } else {
                 // No writers were waiting, the lock is released
                 rtassert!(rguard.queue_empty());
@@ -117,21 +118,26 @@
         rguard: SpinMutexGuard<'_, WaitVariable<Option<NonZeroUsize>>>,
         wguard: SpinMutexGuard<'_, WaitVariable<bool>>,
     ) {
-        if let Err(mut wguard) = WaitQueue::notify_one(wguard) {
-            // No writers waiting, release the write lock
-            *wguard.lock_var_mut() = false;
-            if let Ok(mut rguard) = WaitQueue::notify_all(rguard) {
-                // One or more readers were waiting, pass the lock to them
-                if let NotifiedTcs::All { count } = rguard.notified_tcs() {
-                    *rguard.lock_var_mut() = Some(count)
+        match WaitQueue::notify_one(wguard) {
+            Err(mut wguard) => {
+                // No writers waiting, release the write lock
+                *wguard.lock_var_mut() = false;
+                if let Ok(mut rguard) = WaitQueue::notify_all(rguard) {
+                    // One or more readers were waiting, pass the lock to them
+                    if let NotifiedTcs::All { count } = rguard.notified_tcs() {
+                        *rguard.lock_var_mut() = Some(count)
+                    } else {
+                        unreachable!() // called notify_all
+                    }
+                    rguard.drop_after(wguard);
                 } else {
-                    unreachable!() // called notify_all
+                    // No readers waiting, the lock is released
                 }
-            } else {
-                // No readers waiting, the lock is released
+            },
+            Ok(wguard) => {
+                // There was a thread waiting for write, just pass the lock
+                wguard.drop_after(rguard);
             }
-        } else {
-            // There was a thread waiting for write, just pass the lock
         }
     }
 
diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs
index d542f9b..3cb40e50 100644
--- a/src/libstd/sys/sgx/waitqueue.rs
+++ b/src/libstd/sys/sgx/waitqueue.rs
@@ -98,6 +98,12 @@
     pub fn notified_tcs(&self) -> NotifiedTcs {
         self.notified_tcs
     }
+
+    /// Drop this `WaitGuard`, after dropping another `guard`.
+    pub fn drop_after<U>(self, guard: U) {
+        drop(guard);
+        drop(self);
+    }
 }
 
 impl<'a, T> Deref for WaitGuard<'a, T> {
@@ -140,7 +146,7 @@
     /// until a wakeup event.
     ///
     /// This function does not return until this thread has been awoken.
-    pub fn wait<T>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>) {
+    pub fn wait<T, F: FnOnce()>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>, before_wait: F) {
         // very unsafe: check requirements of UnsafeList::push
         unsafe {
             let mut entry = UnsafeListEntry::new(SpinMutex::new(WaitEntry {
@@ -149,6 +155,7 @@
             }));
             let entry = guard.queue.inner.push(&mut entry);
             drop(guard);
+            before_wait();
             while !entry.lock().wake {
                 // don't panic, this would invalidate `entry` during unwinding
                 let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE));
@@ -545,7 +552,7 @@
             assert!(WaitQueue::notify_one(wq2.lock()).is_ok());
         });
 
-        WaitQueue::wait(locked);
+        WaitQueue::wait(locked, ||{});
 
         t1.join().unwrap();
     }
diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs
index bba4b21..056a203 100644
--- a/src/libstd/sys/unix/process/mod.rs
+++ b/src/libstd/sys/unix/process/mod.rs
@@ -1,5 +1,6 @@
 pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes};
 pub use self::process_inner::Process;
+pub use crate::ffi::OsString as EnvKey;
 
 mod process_common;
 #[cfg(not(target_os = "fuchsia"))]
diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs
index 21fca23..713d308 100644
--- a/src/libstd/sys/unix/process/process_common.rs
+++ b/src/libstd/sys/unix/process/process_common.rs
@@ -1,19 +1,27 @@
 use crate::os::unix::prelude::*;
 
-use crate::ffi::{OsString, OsStr, CString, CStr};
+use crate::ffi::{OsString, OsStr, CString};
 use crate::fmt;
 use crate::io;
 use crate::ptr;
 use crate::sys::fd::FileDesc;
-use crate::sys::fs::{File, OpenOptions};
+use crate::sys::fs::File;
 use crate::sys::pipe::{self, AnonPipe};
-use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::sys_common::process::CommandEnv;
 use crate::collections::BTreeMap;
 
+#[cfg(not(target_os = "fuchsia"))]
+use {
+    crate::ffi::CStr,
+    crate::sys::fs::OpenOptions,
+};
+
 use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE};
 
 cfg_if::cfg_if! {
-    if #[cfg(target_os = "redox")] {
+    if #[cfg(target_os = "fuchsia")] {
+        // fuchsia doesn't have /dev/null
+    } else if #[cfg(target_os = "redox")] {
         const DEV_NULL: &'static str = "null:\0";
     } else {
         const DEV_NULL: &'static str = "/dev/null\0";
@@ -69,7 +77,7 @@
     program: CString,
     args: Vec<CString>,
     argv: Argv,
-    env: CommandEnv<DefaultEnvKey>,
+    env: CommandEnv,
 
     cwd: Option<CString>,
     uid: Option<uid_t>,
@@ -107,6 +115,11 @@
     Inherit,
     Explicit(c_int),
     Owned(FileDesc),
+
+    // On Fuchsia, null stdio is the default, so we simply don't specify
+    // any actions at the time of spawning.
+    #[cfg(target_os = "fuchsia")]
+    Null,
 }
 
 pub enum Stdio {
@@ -201,7 +214,7 @@
         self.stderr = Some(stderr);
     }
 
-    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+    pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
     }
 
@@ -271,7 +284,7 @@
     }
 }
 
-fn construct_envp(env: BTreeMap<DefaultEnvKey, OsString>, saw_nul: &mut bool) -> CStringArray {
+fn construct_envp(env: BTreeMap<OsString, OsString>, saw_nul: &mut bool) -> CStringArray {
     let mut result = CStringArray::with_capacity(env.len());
     for (k, v) in env {
         let mut k: OsString = k.into();
@@ -325,6 +338,7 @@
                 Ok((ChildStdio::Owned(theirs.into_fd()), Some(ours)))
             }
 
+            #[cfg(not(target_os = "fuchsia"))]
             Stdio::Null => {
                 let mut opts = OpenOptions::new();
                 opts.read(readable);
@@ -335,6 +349,11 @@
                 let fd = File::open_c(&path, &opts)?;
                 Ok((ChildStdio::Owned(fd.into_fd()), None))
             }
+
+            #[cfg(target_os = "fuchsia")]
+            Stdio::Null => {
+                Ok((ChildStdio::Null, None))
+            }
         }
     }
 }
@@ -357,6 +376,9 @@
             ChildStdio::Inherit => None,
             ChildStdio::Explicit(fd) => Some(fd),
             ChildStdio::Owned(ref fd) => Some(fd.raw()),
+
+            #[cfg(target_os = "fuchsia")]
+            ChildStdio::Null => None,
         }
     }
 }
diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs
index 7c6be9b..fff9fc6 100644
--- a/src/libstd/sys/unix/process/process_fuchsia.rs
+++ b/src/libstd/sys/unix/process/process_fuchsia.rs
@@ -48,30 +48,51 @@
         use crate::sys::process::zircon::*;
 
         let envp = match maybe_envp {
-            Some(envp) => envp.as_ptr(),
+            // None means to clone the current environment, which is done in the
+            // flags below.
             None => ptr::null(),
+            Some(envp) => envp.as_ptr(),
         };
 
-        let transfer_or_clone = |opt_fd, target_fd| if let Some(local_fd) = opt_fd {
-            fdio_spawn_action_t {
-                action: FDIO_SPAWN_ACTION_TRANSFER_FD,
-                local_fd,
-                target_fd,
-                ..Default::default()
-            }
-        } else {
-            fdio_spawn_action_t {
-                action: FDIO_SPAWN_ACTION_CLONE_FD,
-                local_fd: target_fd,
-                target_fd,
-                ..Default::default()
+        let make_action = |local_io: &ChildStdio, target_fd| -> io::Result<fdio_spawn_action_t> {
+            if let Some(local_fd) = local_io.fd() {
+                Ok(fdio_spawn_action_t {
+                    action: FDIO_SPAWN_ACTION_TRANSFER_FD,
+                    local_fd,
+                    target_fd,
+                    ..Default::default()
+                })
+            } else {
+                if let ChildStdio::Null = local_io {
+                    // acts as no-op
+                    return Ok(Default::default());
+                }
+
+                let mut handle = ZX_HANDLE_INVALID;
+                let status = fdio_fd_clone(target_fd, &mut handle);
+                if status == ERR_INVALID_ARGS || status == ERR_NOT_SUPPORTED {
+                    // This descriptor is closed; skip it rather than generating an
+                    // error.
+                    return Ok(Default::default());
+                }
+                zx_cvt(status)?;
+
+                let mut cloned_fd = 0;
+                zx_cvt(fdio_fd_create(handle, &mut cloned_fd))?;
+
+                Ok(fdio_spawn_action_t {
+                    action: FDIO_SPAWN_ACTION_TRANSFER_FD,
+                    local_fd: cloned_fd as i32,
+                    target_fd,
+                    ..Default::default()
+                })
             }
         };
 
         // Clone stdin, stdout, and stderr
-        let action1 = transfer_or_clone(stdio.stdin.fd(), 0);
-        let action2 = transfer_or_clone(stdio.stdout.fd(), 1);
-        let action3 = transfer_or_clone(stdio.stderr.fd(), 2);
+        let action1 = make_action(&stdio.stdin, 0)?;
+        let action2 = make_action(&stdio.stdout, 1)?;
+        let action3 = make_action(&stdio.stderr, 2)?;
         let actions = [action1, action2, action3];
 
         // We don't want FileDesc::drop to be called on any stdio. fdio_spawn_etc
@@ -84,9 +105,11 @@
 
         let mut process_handle: zx_handle_t = 0;
         zx_cvt(fdio_spawn_etc(
-            0,
-            FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE,
-            self.get_argv()[0], self.get_argv().as_ptr(), envp, 3, actions.as_ptr(),
+            ZX_HANDLE_INVALID,
+            FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE
+            | FDIO_SPAWN_CLONE_ENVIRON,  // this is ignored when envp is non-null
+            self.get_argv()[0], self.get_argv().as_ptr(), envp,
+            actions.len() as size_t, actions.as_ptr(),
             &mut process_handle,
             ptr::null_mut(),
         ))?;
diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs
index ec715d5..1ba48de 100644
--- a/src/libstd/sys/unix/process/zircon.rs
+++ b/src/libstd/sys/unix/process/zircon.rs
@@ -2,8 +2,9 @@
 
 use crate::convert::TryInto;
 use crate::io;
+use crate::i64;
+use crate::mem::MaybeUninit;
 use crate::os::raw::c_char;
-use crate::u64;
 
 use libc::{c_int, c_void, size_t};
 
@@ -14,8 +15,8 @@
 
 pub const ZX_HANDLE_INVALID: zx_handle_t = 0;
 
-pub type zx_time_t = u64;
-pub const ZX_TIME_INFINITE : zx_time_t = u64::MAX;
+pub type zx_time_t = i64;
+pub const ZX_TIME_INFINITE : zx_time_t = i64::MAX;
 
 pub type zx_signals_t = u32;
 
@@ -120,8 +121,11 @@
 extern {
     pub fn fdio_spawn_etc(job: zx_handle_t, flags: u32, path: *const c_char,
                           argv: *const *const c_char, envp: *const *const c_char,
-                          action_count: u64, actions: *const fdio_spawn_action_t,
+                          action_count: size_t, actions: *const fdio_spawn_action_t,
                           process: *mut zx_handle_t, err_msg: *mut c_char) -> zx_status_t;
+
+    pub fn fdio_fd_clone(fd: c_int, out_handle: *mut zx_handle_t) -> zx_status_t;
+    pub fn fdio_fd_create(handle: zx_handle_t, fd: *mut c_int) -> zx_status_t;
 }
 
 // fdio_spawn_etc flags
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
index 02f377d..fd6796a 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -311,6 +311,7 @@
         pub fn actually_monotonic() -> bool {
             (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64")) ||
             (cfg!(target_os = "linux") && cfg!(target_arch = "x86")) ||
+            cfg!(target_os = "fuchsia") ||
             false // last clause, used so `||` is always trailing above
         }
 
diff --git a/src/libstd/sys/vxworks/backtrace/mod.rs b/src/libstd/sys/vxworks/backtrace/mod.rs
deleted file mode 100644
index 0887e5a..0000000
--- a/src/libstd/sys/vxworks/backtrace/mod.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-/// Backtrace support built on libgcc with some extra OS-specific support
-///
-/// Some methods of getting a backtrace:
-///
-/// * The backtrace() functions on unix. It turns out this doesn't work very
-///   well for green threads on macOS, and the address to symbol portion of it
-///   suffers problems that are described below.
-///
-/// * Using libunwind. This is more difficult than it sounds because libunwind
-///   isn't installed everywhere by default. It's also a bit of a hefty library,
-///   so possibly not the best option. When testing, libunwind was excellent at
-///   getting both accurate backtraces and accurate symbols across platforms.
-///   This route was not chosen in favor of the next option, however.
-///
-/// * We're already using libgcc_s for exceptions in rust (triggering thread
-///   unwinding and running destructors on the stack), and it turns out that it
-///   conveniently comes with a function that also gives us a backtrace. All of
-///   these functions look like _Unwind_*, but it's not quite the full
-///   repertoire of the libunwind API. Due to it already being in use, this was
-///   the chosen route of getting a backtrace.
-///
-/// After choosing libgcc_s for backtraces, the sad part is that it will only
-/// give us a stack trace of instruction pointers. Thankfully these instruction
-/// pointers are accurate (they work for green and native threads), but it's
-/// then up to us again to figure out how to translate these addresses to
-/// symbols. As with before, we have a few options. Before, that, a little bit
-/// of an interlude about symbols. This is my very limited knowledge about
-/// symbol tables, and this information is likely slightly wrong, but the
-/// general idea should be correct.
-///
-/// When talking about symbols, it's helpful to know a few things about where
-/// symbols are located. Some symbols are located in the dynamic symbol table
-/// of the executable which in theory means that they're available for dynamic
-/// linking and lookup. Other symbols end up only in the local symbol table of
-/// the file. This loosely corresponds to pub and priv functions in Rust.
-///
-/// Armed with this knowledge, we know that our solution for address to symbol
-/// translation will need to consult both the local and dynamic symbol tables.
-/// With that in mind, here's our options of translating an address to
-/// a symbol.
-///
-/// * Use dladdr(). The original backtrace()-based idea actually uses dladdr()
-///   behind the scenes to translate, and this is why backtrace() was not used.
-///   Conveniently, this method works fantastically on macOS. It appears dladdr()
-///   uses magic to consult the local symbol table, or we're putting everything
-///   in the dynamic symbol table anyway. Regardless, for macOS, this is the
-///   method used for translation. It's provided by the system and easy to do.o
-///
-///   Sadly, all other systems have a dladdr() implementation that does not
-///   consult the local symbol table. This means that most functions are blank
-///   because they don't have symbols. This means that we need another solution.
-///
-/// * Use unw_get_proc_name(). This is part of the libunwind api (not the
-///   libgcc_s version of the libunwind api), but involves taking a dependency
-///   to libunwind. We may pursue this route in the future if we bundle
-///   libunwind, but libunwind was unwieldy enough that it was not chosen at
-///   this time to provide this functionality.
-///
-/// * Shell out to a utility like `readelf`. Crazy though it may sound, it's a
-///   semi-reasonable solution. The stdlib already knows how to spawn processes,
-///   so in theory it could invoke readelf, parse the output, and consult the
-///   local/dynamic symbol tables from there. This ended up not getting chosen
-///   due to the craziness of the idea plus the advent of the next option.
-///
-/// * Use `libbacktrace`. It turns out that this is a small library bundled in
-///   the gcc repository which provides backtrace and symbol translation
-///   functionality. All we really need from it is the backtrace functionality,
-///   and we only really need this on everything that's not macOS, so this is the
-///   chosen route for now.
-///
-/// In summary, the current situation uses libgcc_s to get a trace of stack
-/// pointers, and we use dladdr() or libbacktrace to translate these addresses
-/// to symbols. This is a bit of a hokey implementation as-is, but it works for
-/// all unix platforms we support right now, so it at least gets the job done.
-
-pub use self::tracing::unwind_backtrace;
-pub use self::printing::{foreach_symbol_fileline, resolve_symname};
-
-// tracing impls:
-mod tracing;
-// symbol resolvers:
-mod printing;
-
-#[cfg(not(target_os = "emscripten"))]
-pub mod gnu {
-    use crate::io;
-    use crate::fs;
-
-    use libc::c_char;
-
-    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
-    pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
-        Err(io::Error::new(io::ErrorKind::Other, "Not implemented"))
-    }
-
-    #[cfg(any(target_os = "macos", target_os = "ios"))]
-    pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
-        use crate::env;
-        use crate::os::unix::ffi::OsStrExt;
-
-        let filename = env::current_exe()?;
-        let file = fs::File::open(&filename)?;
-        let mut filename_cstr: Vec<_> = filename.as_os_str().as_bytes().iter()
-            .map(|&x| x as c_char).collect();
-        filename_cstr.push(0); // Null terminate
-        Ok((filename_cstr, file))
-    }
-}
-
-pub struct BacktraceContext;
diff --git a/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs b/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs
deleted file mode 100644
index 202164d..0000000
--- a/src/libstd/sys/vxworks/backtrace/printing/dladdr.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use crate::io;
-use crate::intrinsics;
-use crate::ffi::CStr;
-use crate::sys::backtrace::BacktraceContext;
-use crate::sys_common::backtrace::Frame;
-
-pub fn resolve_symname<F>(frame: Frame,
-                          callback: F,
-                          _: &BacktraceContext) -> io::Result<()>
-    where F: FnOnce(Option<&str>) -> io::Result<()>
-{
-    unsafe {
-        let mut info: Dl_info = intrinsics::init();
-        let symname = if dladdr(frame.exact_position as *mut _, &mut info) == 0 ||
-                         info.dli_sname.is_null() {
-            None
-        } else {
-            CStr::from_ptr(info.dli_sname).to_str().ok()
-        };
-        callback(symname)
-    }
-}
-
-#[repr(C)]
-struct Dl_info {
-    dli_fname: *const libc::c_char,
-    dli_fbase: *mut libc::c_void,
-    dli_sname: *const libc::c_char,
-    dli_saddr: *mut libc::c_void,
-}
-
-extern {
-    #[ link_name = "_rtld_dladdr" ]
-    fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int;
-}
diff --git a/src/libstd/sys/vxworks/backtrace/printing/mod.rs b/src/libstd/sys/vxworks/backtrace/printing/mod.rs
deleted file mode 100644
index d090cae..0000000
--- a/src/libstd/sys/vxworks/backtrace/printing/mod.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-mod dladdr;
-
-use crate::sys::backtrace::BacktraceContext;
-use crate::sys_common::backtrace::Frame;
-use crate::io;
-
-#[cfg(target_os = "emscripten")]
-pub use self::dladdr::resolve_symname;
-
-#[cfg(target_os = "emscripten")]
-pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool>
-where
-    F: FnMut(&[u8], u32) -> io::Result<()>
-{
-    Ok(false)
-}
-
-#[cfg(not(target_os = "emscripten"))]
-pub use crate::sys_common::gnu::libbacktrace::foreach_symbol_fileline;
-
-#[cfg(not(target_os = "emscripten"))]
-pub fn resolve_symname<F>(frame: Frame, callback: F, bc: &BacktraceContext) -> io::Result<()>
-where
-    F: FnOnce(Option<&str>) -> io::Result<()>
-{
-    crate::sys_common::gnu::libbacktrace::resolve_symname(frame, |symname| {
-        if symname.is_some() {
-            callback(symname)
-        } else {
-            dladdr::resolve_symname(frame, callback, bc)
-        }
-    }, bc)
-}
diff --git a/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs
deleted file mode 100644
index a628d10..0000000
--- a/src/libstd/sys/vxworks/backtrace/tracing/backtrace_fn.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-/// As always - iOS on arm uses SjLj exceptions and
-/// _Unwind_Backtrace is even not available there. Still,
-/// backtraces could be extracted using a backtrace function,
-/// which thanks god is public
-///
-/// As mentioned in a huge comment block in `super::super`, backtrace
-/// doesn't play well with green threads, so while it is extremely nice and
-/// simple to use it should be used only on iOS devices as the only viable
-/// option.
-
-use crate::io;
-use crate::ptr;
-use crate::sys::backtrace::BacktraceContext;
-use crate::sys_common::backtrace::Frame;
-
-#[inline(never)] // if we know this is a function call, we can skip it when
-                 // tracing
-pub fn unwind_backtrace(frames: &mut [Frame])
-    -> io::Result<(usize, BacktraceContext)>
-{
-    const FRAME_LEN: usize = 100;
-    assert!(FRAME_LEN >= frames.len());
-    let mut raw_frames = [ptr::null_mut(); FRAME_LEN];
-    let nb_frames = unsafe {
-        backtrace(raw_frames.as_mut_ptr(), raw_frames.len() as libc::c_int)
-    } as usize;
-    for (from, to) in raw_frames.iter().zip(frames.iter_mut()).take(nb_frames) {
-        *to = Frame {
-            exact_position: *from as *mut u8,
-            symbol_addr: *from as *mut u8,
-            inline_context: 0,
-        };
-    }
-    Ok((nb_frames as usize, BacktraceContext))
-}
-
-extern {
-    fn backtrace(buf: *mut *mut libc::c_void, sz: libc::c_int) -> libc::c_int;
-}
diff --git a/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs b/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs
deleted file mode 100644
index e637913..0000000
--- a/src/libstd/sys/vxworks/backtrace/tracing/gcc_s.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-use crate::error::Error;
-use crate::fmt;
-use crate::io;
-use crate::sys::backtrace::BacktraceContext;
-use crate::sys_common::backtrace::Frame;
-
-use unwind as uw;
-
-struct Context<'a> {
-    idx: usize,
-    frames: &'a mut [Frame],
-}
-
-#[derive(Debug)]
-struct UnwindError(uw::_Unwind_Reason_Code);
-
-impl Error for UnwindError {
-    fn description(&self) -> &'static str {
-        "unexpected return value while unwinding"
-    }
-}
-
-impl fmt::Display for UnwindError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}: {:?}", self.description(), self.0)
-    }
-}
-
-#[inline(never)] // if we know this is a function call, we can skip it when
-                 // tracing
-pub fn unwind_backtrace(frames: &mut [Frame])
-    -> io::Result<(usize, BacktraceContext)>
-{
-    let mut cx = Context {
-        idx: 0,
-        frames,
-    };
-    let result_unwind = unsafe {
-        uw::_Unwind_Backtrace(trace_fn,
-                              &mut cx as *mut Context<'_>
-                              as *mut libc::c_void)
-    };
-    // See libunwind:src/unwind/Backtrace.c for the return values.
-    // No, there is no doc.
-    match result_unwind {
-        // These return codes seem to be benign and need to be ignored for backtraces
-        // to show up properly on all tested platforms.
-        uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
-            Ok((cx.idx, BacktraceContext))
-        }
-        _ => {
-            Err(io::Error::new(io::ErrorKind::Other,
-                               UnwindError(result_unwind)))
-        }
-    }
-}
-
-extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
-                   arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
-    let cx = unsafe { &mut *(arg as *mut Context<'_>) };
-    if cx.idx >= cx.frames.len() {
-        return uw::_URC_NORMAL_STOP;
-    }
-
-    let mut ip_before_insn = 0;
-    let mut ip = unsafe {
-        uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void
-    };
-    if !ip.is_null() && ip_before_insn == 0 {
-        // this is a non-signaling frame, so `ip` refers to the address
-        // after the calling instruction. account for that.
-        ip = (ip as usize - 1) as *mut _;
-    }
-
-    // dladdr() on osx gets whiny when we use FindEnclosingFunction, and
-    // it appears to work fine without it, so we only use
-    // FindEnclosingFunction on non-osx platforms. In doing so, we get a
-    // slightly more accurate stack trace in the process.
-    //
-    // This is often because panic involves the last instruction of a
-    // function being "call std::rt::begin_unwind", with no ret
-    // instructions after it. This means that the return instruction
-    // pointer points *outside* of the calling function, and by
-    // unwinding it we go back to the original function.
-    let symaddr = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
-        ip
-    } else {
-        unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
-    };
-
-    cx.frames[cx.idx] = Frame {
-        symbol_addr: symaddr as *mut u8,
-        exact_position: ip as *mut u8,
-        inline_context: 0,
-    };
-    cx.idx += 1;
-
-    uw::_URC_NO_REASON
-}
diff --git a/src/libstd/sys/vxworks/backtrace/tracing/mod.rs b/src/libstd/sys/vxworks/backtrace/tracing/mod.rs
deleted file mode 100644
index 11863e6..0000000
--- a/src/libstd/sys/vxworks/backtrace/tracing/mod.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-pub use self::imp::*;
-
-#[cfg(not(all(target_os = "ios", target_arch = "arm")))]
-#[path = "gcc_s.rs"]
-mod imp;
-#[cfg(all(target_os = "ios", target_arch = "arm"))]
-#[path = "backtrace_fn.rs"]
-mod imp;
diff --git a/src/libstd/sys/vxworks/fast_thread_local.rs b/src/libstd/sys/vxworks/fast_thread_local.rs
index 2e02198..8b55939 100644
--- a/src/libstd/sys/vxworks/fast_thread_local.rs
+++ b/src/libstd/sys/vxworks/fast_thread_local.rs
@@ -1,5 +1,3 @@
-// Copyright (c) 2019 Wind River Systems, Inc.
-
 #![cfg(target_thread_local)]
 #![unstable(feature = "thread_local_internals", issue = "0")]
 
diff --git a/src/libstd/sys/vxworks/process/mod.rs b/src/libstd/sys/vxworks/process/mod.rs
index 4dc7060..1fc88fb 100644
--- a/src/libstd/sys/vxworks/process/mod.rs
+++ b/src/libstd/sys/vxworks/process/mod.rs
@@ -1,5 +1,6 @@
 pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes};
 pub use self::process_inner::Process;
+pub use crate::ffi::OsString as EnvKey;
 
 mod process_common;
 #[path = "process_vxworks.rs"]
diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs
index ba79735..13648ab 100644
--- a/src/libstd/sys/vxworks/process/process_common.rs
+++ b/src/libstd/sys/vxworks/process/process_common.rs
@@ -7,7 +7,7 @@
 use crate::sys::fd::FileDesc;
 use crate::sys::fs::{File, OpenOptions};
 use crate::sys::pipe::{self, AnonPipe};
-use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::sys_common::process::CommandEnv;
 use crate::collections::BTreeMap;
 
 use libc::{c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE};
@@ -37,7 +37,7 @@
     program: CString,
     args: Vec<CString>,
     argv: Argv,
-    env: CommandEnv<DefaultEnvKey>,
+    env: CommandEnv,
 
     cwd: Option<CString>,
     uid: Option<uid_t>,
@@ -170,7 +170,7 @@
         self.stderr = Some(stderr);
     }
 
-    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+    pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
     }
 
@@ -240,7 +240,7 @@
     }
 }
 
-fn construct_envp(env: BTreeMap<DefaultEnvKey, OsString>, saw_nul: &mut bool) -> CStringArray {
+fn construct_envp(env: BTreeMap<OsString, OsString>, saw_nul: &mut bool) -> CStringArray {
     let mut result = CStringArray::with_capacity(env.len());
     for (k, v) in env {
         let mut k: OsString = k.into();
diff --git a/src/libstd/sys/vxworks/process/process_vxworks.rs b/src/libstd/sys/vxworks/process/process_vxworks.rs
index b07966f..8780df1 100644
--- a/src/libstd/sys/vxworks/process/process_vxworks.rs
+++ b/src/libstd/sys/vxworks/process/process_vxworks.rs
@@ -5,6 +5,7 @@
 use crate::sys::cvt;
 use crate::sys::process::rtp;
 use crate::sys::process::process_common::*;
+use crate::sys_common::thread;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
@@ -57,8 +58,7 @@
                 self.get_argv().as_ptr() as *const _, // argv
                 *sys::os::environ() as *const *const c_char,
                 100 as c_int,                         // initial priority
-                0x16000,                                    // initial stack size. 0 defaults
-                                                      // to 0x4000 in 32 bit and 0x8000 in 64 bit
+                thread::min_stack(),                  // initial stack size.
                 0,                                    // options
                 0                                     // task options
             );
diff --git a/src/libstd/sys/vxworks/rand.rs b/src/libstd/sys/vxworks/rand.rs
index 1ec0cbe..c22880d 100644
--- a/src/libstd/sys/vxworks/rand.rs
+++ b/src/libstd/sys/vxworks/rand.rs
@@ -14,17 +14,24 @@
 mod imp {
     use libc;
     use crate::io;
-
-    extern "C" {
-        fn randBytes (randBuf: *mut libc::c_uchar,
-                      numOfBytes: libc::c_int) -> libc::c_int;
-    }
+    use core::sync::atomic::{AtomicBool, Ordering::Relaxed};
 
     pub fn fill_bytes(v: &mut [u8]) {
+        static RNG_INIT: AtomicBool = AtomicBool::new(false);
+        while !RNG_INIT.load(Relaxed) {
+            let ret = unsafe { libc::randSecure() };
+            if ret < 0 {
+                panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
+            } else if ret > 0 {
+                RNG_INIT.store(true, Relaxed);
+                break;
+            }
+            unsafe { libc::usleep(10) };
+        }
         let ret = unsafe {
-            randBytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int)
+            libc::randABytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int)
         };
-        if ret == -1 {
+        if ret < 0 {
             panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
         }
     }
diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs
index ef896f6..e4396b0 100644
--- a/src/libstd/sys/vxworks/thread.rs
+++ b/src/libstd/sys/vxworks/thread.rs
@@ -8,7 +8,7 @@
 
 use crate::sys_common::thread::*;
 
-pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
+pub const DEFAULT_MIN_STACK_SIZE: usize = 0x40000; // 256K
 
 pub struct Thread {
     id: libc::pthread_t,
diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs
index 8b4b354..3280c49 100644
--- a/src/libstd/sys/wasi/args.rs
+++ b/src/libstd/sys/wasi/args.rs
@@ -1,11 +1,10 @@
-use crate::ffi::CStr;
-use crate::io;
-use crate::sys::cvt_wasi;
 use crate::ffi::OsString;
 use crate::marker::PhantomData;
 use crate::os::wasi::ffi::OsStringExt;
 use crate::vec;
 
+use ::wasi::wasi_unstable as wasi;
+
 pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
 }
 
@@ -19,31 +18,17 @@
 
 /// Returns the command line arguments
 pub fn args() -> Args {
-    maybe_args().unwrap_or_else(|_| {
-        Args {
-            iter: Vec::new().into_iter(),
-            _dont_send_or_sync_me: PhantomData
-        }
-    })
-}
-
-fn maybe_args() -> io::Result<Args> {
-    unsafe {
-        let (mut argc, mut argv_buf_size) = (0, 0);
-        cvt_wasi(libc::__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?;
-
-        let mut argc = vec![core::ptr::null_mut::<libc::c_char>(); argc];
-        let mut argv_buf = vec![0; argv_buf_size];
-        cvt_wasi(libc::__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?;
-
-        let args = argc.into_iter()
-            .map(|ptr| CStr::from_ptr(ptr).to_bytes().to_vec())
-            .map(|bytes| OsString::from_vec(bytes))
-            .collect::<Vec<_>>();
-        Ok(Args {
-            iter: args.into_iter(),
-            _dont_send_or_sync_me: PhantomData,
-        })
+    let buf = wasi::args_sizes_get().and_then(|args_sizes| {
+        let mut buf = Vec::with_capacity(args_sizes.get_count());
+        wasi::args_get(args_sizes, |arg| {
+            let arg = OsString::from_vec(arg.to_vec());
+            buf.push(arg);
+        })?;
+        Ok(buf)
+    }).unwrap_or(vec![]);
+    Args {
+        iter: buf.into_iter(),
+        _dont_send_or_sync_me: PhantomData
     }
 }
 
diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs
index 0ec4122..9fa4abf 100644
--- a/src/libstd/sys/wasi/ext/fs.rs
+++ b/src/libstd/sys/wasi/ext/fs.rs
@@ -8,6 +8,8 @@
 use crate::path::{Path, PathBuf};
 use crate::sys_common::{AsInner, AsInnerMut, FromInner};
 
+use ::wasi::wasi_unstable as wasi;
+
 /// WASI-specific extensions to [`File`].
 ///
 /// [`File`]: ../../../../std/fs/struct.File.html
@@ -336,16 +338,16 @@
 
 impl FileTypeExt for fs::FileType {
     fn is_block_device(&self) -> bool {
-        self.as_inner().bits() == libc::__WASI_FILETYPE_BLOCK_DEVICE
+        self.as_inner().bits() == wasi::FILETYPE_BLOCK_DEVICE
     }
     fn is_character_device(&self) -> bool {
-        self.as_inner().bits() == libc::__WASI_FILETYPE_CHARACTER_DEVICE
+        self.as_inner().bits() == wasi::FILETYPE_CHARACTER_DEVICE
     }
     fn is_socket_dgram(&self) -> bool {
-        self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_DGRAM
+        self.as_inner().bits() == wasi::FILETYPE_SOCKET_DGRAM
     }
     fn is_socket_stream(&self) -> bool {
-        self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_STREAM
+        self.as_inner().bits() == wasi::FILETYPE_SOCKET_STREAM
     }
 }
 
diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs
index 12afd1d..f1839df 100644
--- a/src/libstd/sys/wasi/ext/io.rs
+++ b/src/libstd/sys/wasi/ext/io.rs
@@ -8,6 +8,8 @@
 use crate::net;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
+use ::wasi::wasi_unstable as wasi;
+
 /// Raw file descriptors.
 pub type RawFd = u32;
 
@@ -125,18 +127,18 @@
 
 impl AsRawFd for io::Stdin {
     fn as_raw_fd(&self) -> RawFd {
-        libc::STDIN_FILENO as u32
+        wasi::STDIN_FD
     }
 }
 
 impl AsRawFd for io::Stdout {
     fn as_raw_fd(&self) -> RawFd {
-        libc::STDOUT_FILENO as u32
+        wasi::STDOUT_FD
     }
 }
 
 impl AsRawFd for io::Stderr {
     fn as_raw_fd(&self) -> RawFd {
-        libc::STDERR_FILENO as u32
+        wasi::STDERR_FD
     }
 }
diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs
index 25692ec..5b7a867 100644
--- a/src/libstd/sys/wasi/fd.rs
+++ b/src/libstd/sys/wasi/fd.rs
@@ -3,348 +3,248 @@
 use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
 use crate::mem;
 use crate::net::Shutdown;
-use crate::sys::cvt_wasi;
-use libc::{self, c_char, c_void};
+use super::err2io;
+use ::wasi::wasi_unstable as wasi;
 
 #[derive(Debug)]
 pub struct WasiFd {
-    fd: libc::__wasi_fd_t,
+    fd: wasi::Fd,
 }
 
-// FIXME: these should probably all be fancier structs, builders, enums, etc
-pub type LookupFlags = u32;
-pub type FdFlags = u16;
-pub type Advice = u8;
-pub type Rights = u64;
-pub type Oflags = u16;
-pub type DirCookie = u64;
-pub type Timestamp = u64;
-pub type FstFlags = u16;
-pub type RiFlags = u16;
-pub type RoFlags = u16;
-pub type SiFlags = u16;
-
-fn iovec(a: &mut [IoSliceMut<'_>]) -> (*const libc::__wasi_iovec_t, usize) {
+fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::IoVec] {
     assert_eq!(
         mem::size_of::<IoSliceMut<'_>>(),
-        mem::size_of::<libc::__wasi_iovec_t>()
+        mem::size_of::<wasi::IoVec>()
     );
     assert_eq!(
         mem::align_of::<IoSliceMut<'_>>(),
-        mem::align_of::<libc::__wasi_iovec_t>()
+        mem::align_of::<wasi::IoVec>()
     );
-    (a.as_ptr() as *const libc::__wasi_iovec_t, a.len())
+    /// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
+    unsafe { mem::transmute(a) }
 }
 
-fn ciovec(a: &[IoSlice<'_>]) -> (*const libc::__wasi_ciovec_t, usize) {
+fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::CIoVec] {
     assert_eq!(
         mem::size_of::<IoSlice<'_>>(),
-        mem::size_of::<libc::__wasi_ciovec_t>()
+        mem::size_of::<wasi::CIoVec>()
     );
     assert_eq!(
         mem::align_of::<IoSlice<'_>>(),
-        mem::align_of::<libc::__wasi_ciovec_t>()
+        mem::align_of::<wasi::CIoVec>()
     );
-    (a.as_ptr() as *const libc::__wasi_ciovec_t, a.len())
+    /// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
+    unsafe { mem::transmute(a) }
 }
 
 impl WasiFd {
-    pub unsafe fn from_raw(fd: libc::__wasi_fd_t) -> WasiFd {
+    pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd {
         WasiFd { fd }
     }
 
-    pub fn into_raw(self) -> libc::__wasi_fd_t {
+    pub fn into_raw(self) -> wasi::Fd {
         let ret = self.fd;
         mem::forget(self);
         ret
     }
 
-    pub fn as_raw(&self) -> libc::__wasi_fd_t {
+    pub fn as_raw(&self) -> wasi::Fd {
         self.fd
     }
 
     pub fn datasync(&self) -> io::Result<()> {
-        cvt_wasi(unsafe { libc::__wasi_fd_datasync(self.fd) })
+        unsafe { wasi::fd_datasync(self.fd).map_err(err2io) }
     }
 
     pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
-        let mut read = 0;
-        let (ptr, len) = iovec(bufs);
-        cvt_wasi(unsafe { libc::__wasi_fd_pread(self.fd, ptr, len, offset, &mut read) })?;
-        Ok(read)
+        unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) }
     }
 
     pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
-        let mut read = 0;
-        let (ptr, len) = ciovec(bufs);
-        cvt_wasi(unsafe { libc::__wasi_fd_pwrite(self.fd, ptr, len, offset, &mut read) })?;
-        Ok(read)
+        unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) }
     }
 
     pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        let mut read = 0;
-        let (ptr, len) = iovec(bufs);
-        cvt_wasi(unsafe { libc::__wasi_fd_read(self.fd, ptr, len, &mut read) })?;
-        Ok(read)
+        unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) }
     }
 
     pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let mut read = 0;
-        let (ptr, len) = ciovec(bufs);
-        cvt_wasi(unsafe { libc::__wasi_fd_write(self.fd, ptr, len, &mut read) })?;
-        Ok(read)
+        unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) }
     }
 
     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
         let (whence, offset) = match pos {
-            SeekFrom::Start(pos) => (libc::__WASI_WHENCE_SET, pos as i64),
-            SeekFrom::End(pos) => (libc::__WASI_WHENCE_END, pos),
-            SeekFrom::Current(pos) => (libc::__WASI_WHENCE_CUR, pos),
+            SeekFrom::Start(pos) => (wasi::WHENCE_SET, pos as i64),
+            SeekFrom::End(pos) => (wasi::WHENCE_END, pos),
+            SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos),
         };
-        let mut pos = 0;
-        cvt_wasi(unsafe { libc::__wasi_fd_seek(self.fd, offset, whence, &mut pos) })?;
-        Ok(pos)
+        unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) }
     }
 
     pub fn tell(&self) -> io::Result<u64> {
-        let mut pos = 0;
-        cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?;
-        Ok(pos)
+        unsafe { wasi::fd_tell(self.fd).map_err(err2io) }
     }
 
     // FIXME: __wasi_fd_fdstat_get
 
-    pub fn set_flags(&self, flags: FdFlags) -> io::Result<()> {
-        cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_flags(self.fd, flags) })
+    pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> {
+        unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) }
     }
 
-    pub fn set_rights(&self, base: Rights, inheriting: Rights) -> io::Result<()> {
-        cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_rights(self.fd, base, inheriting) })
+    pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> {
+        unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) }
     }
 
     pub fn sync(&self) -> io::Result<()> {
-        cvt_wasi(unsafe { libc::__wasi_fd_sync(self.fd) })
+        unsafe { wasi::fd_sync(self.fd).map_err(err2io) }
     }
 
-    pub fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
-        cvt_wasi(unsafe { libc::__wasi_fd_advise(self.fd, offset, len, advice as u8) })
+    pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
+        unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) }
     }
 
     pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
-        cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) })
+        unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) }
     }
 
     pub fn create_directory(&self, path: &[u8]) -> io::Result<()> {
-        cvt_wasi(unsafe {
-            libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len())
-        })
+        unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) }
     }
 
     pub fn link(
         &self,
-        old_flags: LookupFlags,
+        old_flags: wasi::LookupFlags,
         old_path: &[u8],
         new_fd: &WasiFd,
         new_path: &[u8],
     ) -> io::Result<()> {
-        cvt_wasi(unsafe {
-            libc::__wasi_path_link(
-                self.fd,
-                old_flags,
-                old_path.as_ptr() as *const c_char,
-                old_path.len(),
-                new_fd.fd,
-                new_path.as_ptr() as *const c_char,
-                new_path.len(),
-            )
-        })
+        unsafe {
+            wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path)
+                .map_err(err2io)
+        }
     }
 
     pub fn open(
         &self,
-        dirflags: LookupFlags,
+        dirflags: wasi::LookupFlags,
         path: &[u8],
-        oflags: Oflags,
-        fs_rights_base: Rights,
-        fs_rights_inheriting: Rights,
-        fs_flags: FdFlags,
+        oflags: wasi::OFlags,
+        fs_rights_base: wasi::Rights,
+        fs_rights_inheriting: wasi::Rights,
+        fs_flags: wasi::FdFlags,
     ) -> io::Result<WasiFd> {
         unsafe {
-            let mut fd = 0;
-            cvt_wasi(libc::__wasi_path_open(
+            wasi::path_open(
                 self.fd,
                 dirflags,
-                path.as_ptr() as *const c_char,
-                path.len(),
+                path,
                 oflags,
                 fs_rights_base,
                 fs_rights_inheriting,
                 fs_flags,
-                &mut fd,
-            ))?;
-            Ok(WasiFd::from_raw(fd))
+            ).map(|fd| WasiFd::from_raw(fd)).map_err(err2io)
         }
     }
 
-    pub fn readdir(&self, buf: &mut [u8], cookie: DirCookie) -> io::Result<usize> {
-        let mut used = 0;
-        cvt_wasi(unsafe {
-            libc::__wasi_fd_readdir(
-                self.fd,
-                buf.as_mut_ptr() as *mut c_void,
-                buf.len(),
-                cookie,
-                &mut used,
-            )
-        })?;
-        Ok(used)
+    pub fn readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result<usize> {
+        unsafe { wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) }
     }
 
     pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> {
-        let mut used = 0;
-        cvt_wasi(unsafe {
-            libc::__wasi_path_readlink(
-                self.fd,
-                path.as_ptr() as *const c_char,
-                path.len(),
-                buf.as_mut_ptr() as *mut c_char,
-                buf.len(),
-                &mut used,
-            )
-        })?;
-        Ok(used)
+        unsafe { wasi::path_readlink(self.fd, path, buf).map_err(err2io) }
     }
 
     pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> {
-        cvt_wasi(unsafe {
-            libc::__wasi_path_rename(
-                self.fd,
-                old_path.as_ptr() as *const c_char,
-                old_path.len(),
-                new_fd.fd,
-                new_path.as_ptr() as *const c_char,
-                new_path.len(),
-            )
-        })
+        unsafe {
+            wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io)
+        }
     }
 
-    pub fn filestat_get(&self, buf: *mut libc::__wasi_filestat_t) -> io::Result<()> {
-        cvt_wasi(unsafe { libc::__wasi_fd_filestat_get(self.fd, buf) })
+    pub fn filestat_get(&self) -> io::Result<wasi::FileStat> {
+        unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) }
     }
 
     pub fn filestat_set_times(
         &self,
-        atim: Timestamp,
-        mtim: Timestamp,
-        fstflags: FstFlags,
+        atim: wasi::Timestamp,
+        mtim: wasi::Timestamp,
+        fstflags: wasi::FstFlags,
     ) -> io::Result<()> {
-        cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_times(self.fd, atim, mtim, fstflags) })
+        unsafe {
+            wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io)
+        }
     }
 
     pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
-        cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) })
+        unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) }
     }
 
     pub fn path_filestat_get(
         &self,
-        flags: LookupFlags,
+        flags: wasi::LookupFlags,
         path: &[u8],
-        buf: *mut libc::__wasi_filestat_t,
-    ) -> io::Result<()> {
-        cvt_wasi(unsafe {
-            libc::__wasi_path_filestat_get(
-                self.fd,
-                flags,
-                path.as_ptr() as *const c_char,
-                path.len(),
-                buf,
-            )
-        })
+    ) -> io::Result<wasi::FileStat> {
+        unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) }
     }
 
     pub fn path_filestat_set_times(
         &self,
-        flags: LookupFlags,
+        flags: wasi::LookupFlags,
         path: &[u8],
-        atim: Timestamp,
-        mtim: Timestamp,
-        fstflags: FstFlags,
+        atim: wasi::Timestamp,
+        mtim: wasi::Timestamp,
+        fstflags: wasi::FstFlags,
     ) -> io::Result<()> {
-        cvt_wasi(unsafe {
-            libc::__wasi_path_filestat_set_times(
+        unsafe {
+            wasi::path_filestat_set_times(
                 self.fd,
                 flags,
-                path.as_ptr() as *const c_char,
-                path.len(),
+                path,
                 atim,
                 mtim,
                 fstflags,
-            )
-        })
+            ).map_err(err2io)
+        }
     }
 
     pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> {
-        cvt_wasi(unsafe {
-            libc::__wasi_path_symlink(
-                old_path.as_ptr() as *const c_char,
-                old_path.len(),
-                self.fd,
-                new_path.as_ptr() as *const c_char,
-                new_path.len(),
-            )
-        })
+        unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) }
     }
 
     pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> {
-        cvt_wasi(unsafe {
-            libc::__wasi_path_unlink_file(self.fd, path.as_ptr() as *const c_char, path.len())
-        })
+        unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) }
     }
 
     pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> {
-        cvt_wasi(unsafe {
-            libc::__wasi_path_remove_directory(self.fd, path.as_ptr() as *const c_char, path.len())
-        })
+        unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) }
     }
 
     pub fn sock_recv(
         &self,
         ri_data: &mut [IoSliceMut<'_>],
-        ri_flags: RiFlags,
-    ) -> io::Result<(usize, RoFlags)> {
-        let mut ro_datalen = 0;
-        let mut ro_flags = 0;
-        let (ptr, len) = iovec(ri_data);
-        cvt_wasi(unsafe {
-            libc::__wasi_sock_recv(self.fd, ptr, len, ri_flags, &mut ro_datalen, &mut ro_flags)
-        })?;
-        Ok((ro_datalen, ro_flags))
+        ri_flags: wasi::RiFlags,
+    ) -> io::Result<(usize, wasi::RoFlags)> {
+        unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) }
     }
 
-    pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: SiFlags) -> io::Result<usize> {
-        let mut so_datalen = 0;
-        let (ptr, len) = ciovec(si_data);
-        cvt_wasi(unsafe { libc::__wasi_sock_send(self.fd, ptr, len, si_flags, &mut so_datalen) })?;
-        Ok(so_datalen)
+    pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::SiFlags) -> io::Result<usize> {
+        unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) }
     }
 
     pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
         let how = match how {
-            Shutdown::Read => libc::__WASI_SHUT_RD,
-            Shutdown::Write => libc::__WASI_SHUT_WR,
-            Shutdown::Both => libc::__WASI_SHUT_WR | libc::__WASI_SHUT_RD,
+            Shutdown::Read => wasi::SHUT_RD,
+            Shutdown::Write => wasi::SHUT_WR,
+            Shutdown::Both => wasi::SHUT_WR | wasi::SHUT_RD,
         };
-        cvt_wasi(unsafe { libc::__wasi_sock_shutdown(self.fd, how) })?;
-        Ok(())
+        unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) }
     }
 }
 
 impl Drop for WasiFd {
     fn drop(&mut self) {
-        unsafe {
-            // FIXME: can we handle the return code here even though we can't on
-            // unix?
-            libc::__wasi_fd_close(self.fd);
-        }
+        // FIXME: can we handle the return code here even though we can't on
+        // unix?
+        let _ = unsafe { wasi::fd_close(self.fd) };
     }
 }
diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs
index 172c603..4113f6a 100644
--- a/src/libstd/sys/wasi/fs.rs
+++ b/src/libstd/sys/wasi/fs.rs
@@ -7,7 +7,7 @@
 use crate::path::{Path, PathBuf};
 use crate::ptr;
 use crate::sync::Arc;
-use crate::sys::fd::{DirCookie, WasiFd};
+use crate::sys::fd::WasiFd;
 use crate::sys::time::SystemTime;
 use crate::sys::unsupported;
 use crate::sys_common::FromInner;
@@ -15,18 +15,20 @@
 pub use crate::sys_common::fs::copy;
 pub use crate::sys_common::fs::remove_dir_all;
 
+use ::wasi::wasi_unstable as wasi;
+
 pub struct File {
     fd: WasiFd,
 }
 
 #[derive(Clone)]
 pub struct FileAttr {
-    meta: libc::__wasi_filestat_t,
+    meta: wasi::FileStat,
 }
 
 pub struct ReadDir {
     inner: Arc<ReadDirInner>,
-    cookie: Option<DirCookie>,
+    cookie: Option<wasi::DirCookie>,
     buf: Vec<u8>,
     offset: usize,
     cap: usize,
@@ -38,7 +40,7 @@
 }
 
 pub struct DirEntry {
-    meta: libc::__wasi_dirent_t,
+    meta: wasi::Dirent,
     name: Vec<u8>,
     inner: Arc<ReadDirInner>,
 }
@@ -47,11 +49,11 @@
 pub struct OpenOptions {
     read: bool,
     write: bool,
-    dirflags: libc::__wasi_lookupflags_t,
-    fdflags: libc::__wasi_fdflags_t,
-    oflags: libc::__wasi_oflags_t,
-    rights_base: Option<libc::__wasi_rights_t>,
-    rights_inheriting: Option<libc::__wasi_rights_t>,
+    dirflags: wasi::LookupFlags,
+    fdflags: wasi::FdFlags,
+    oflags: wasi::OFlags,
+    rights_base: Option<wasi::Rights>,
+    rights_inheriting: Option<wasi::Rights>,
 }
 
 #[derive(Clone, PartialEq, Eq, Debug)]
@@ -61,19 +63,13 @@
 
 #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
 pub struct FileType {
-    bits: libc::__wasi_filetype_t,
+    bits: wasi::FileType,
 }
 
 #[derive(Debug)]
 pub struct DirBuilder {}
 
 impl FileAttr {
-    fn zero() -> FileAttr {
-        FileAttr {
-            meta: unsafe { mem::zeroed() },
-        }
-    }
-
     pub fn size(&self) -> u64 {
         self.meta.st_size
     }
@@ -101,7 +97,7 @@
         Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim))
     }
 
-    pub fn as_wasi(&self) -> &libc::__wasi_filestat_t {
+    pub fn as_wasi(&self) -> &wasi::FileStat {
         &self.meta
     }
 }
@@ -118,18 +114,18 @@
 
 impl FileType {
     pub fn is_dir(&self) -> bool {
-        self.bits == libc::__WASI_FILETYPE_DIRECTORY
+        self.bits == wasi::FILETYPE_DIRECTORY
     }
 
     pub fn is_file(&self) -> bool {
-        self.bits == libc::__WASI_FILETYPE_REGULAR_FILE
+        self.bits == wasi::FILETYPE_REGULAR_FILE
     }
 
     pub fn is_symlink(&self) -> bool {
-        self.bits == libc::__WASI_FILETYPE_SYMBOLIC_LINK
+        self.bits == wasi::FILETYPE_SYMBOLIC_LINK
     }
 
-    pub fn bits(&self) -> libc::__wasi_filetype_t {
+    pub fn bits(&self) -> wasi::FileType {
         self.bits
     }
 }
@@ -173,7 +169,7 @@
             // must have been truncated at the end of the buffer, so reset our
             // offset so we can go back and reread into the buffer, picking up
             // where we last left off.
-            let dirent_size = mem::size_of::<libc::__wasi_dirent_t>();
+            let dirent_size = mem::size_of::<wasi::Dirent>();
             if data.len() < dirent_size {
                 assert!(self.cookie.is_some());
                 assert!(self.buf.len() >= dirent_size);
@@ -182,7 +178,7 @@
             }
             let (dirent, data) = data.split_at(dirent_size);
             let dirent =
-                unsafe { ptr::read_unaligned(dirent.as_ptr() as *const libc::__wasi_dirent_t) };
+                unsafe { ptr::read_unaligned(dirent.as_ptr() as *const wasi::Dirent) };
 
             // If the file name was truncated, then we need to reinvoke
             // `readdir` so we truncate our buffer to start over and reread this
@@ -241,7 +237,7 @@
         })
     }
 
-    pub fn ino(&self) -> libc::__wasi_inode_t {
+    pub fn ino(&self) -> wasi::Inode {
         self.meta.d_ino
     }
 }
@@ -249,7 +245,7 @@
 impl OpenOptions {
     pub fn new() -> OpenOptions {
         let mut base = OpenOptions::default();
-        base.dirflags = libc::__WASI_LOOKUP_SYMLINK_FOLLOW;
+        base.dirflags = wasi::LOOKUP_SYMLINK_FOLLOW;
         return base;
     }
 
@@ -262,23 +258,23 @@
     }
 
     pub fn truncate(&mut self, truncate: bool) {
-        self.oflag(libc::__WASI_O_TRUNC, truncate);
+        self.oflag(wasi::O_TRUNC, truncate);
     }
 
     pub fn create(&mut self, create: bool) {
-        self.oflag(libc::__WASI_O_CREAT, create);
+        self.oflag(wasi::O_CREAT, create);
     }
 
     pub fn create_new(&mut self, create_new: bool) {
-        self.oflag(libc::__WASI_O_EXCL, create_new);
-        self.oflag(libc::__WASI_O_CREAT, create_new);
+        self.oflag(wasi::O_EXCL, create_new);
+        self.oflag(wasi::O_CREAT, create_new);
     }
 
     pub fn directory(&mut self, directory: bool) {
-        self.oflag(libc::__WASI_O_DIRECTORY, directory);
+        self.oflag(wasi::O_DIRECTORY, directory);
     }
 
-    fn oflag(&mut self, bit: libc::__wasi_oflags_t, set: bool) {
+    fn oflag(&mut self, bit: wasi::OFlags, set: bool) {
         if set {
             self.oflags |= bit;
         } else {
@@ -287,26 +283,26 @@
     }
 
     pub fn append(&mut self, set: bool) {
-        self.fdflag(libc::__WASI_FDFLAG_APPEND, set);
+        self.fdflag(wasi::FDFLAG_APPEND, set);
     }
 
     pub fn dsync(&mut self, set: bool) {
-        self.fdflag(libc::__WASI_FDFLAG_DSYNC, set);
+        self.fdflag(wasi::FDFLAG_DSYNC, set);
     }
 
     pub fn nonblock(&mut self, set: bool) {
-        self.fdflag(libc::__WASI_FDFLAG_NONBLOCK, set);
+        self.fdflag(wasi::FDFLAG_NONBLOCK, set);
     }
 
     pub fn rsync(&mut self, set: bool) {
-        self.fdflag(libc::__WASI_FDFLAG_RSYNC, set);
+        self.fdflag(wasi::FDFLAG_RSYNC, set);
     }
 
     pub fn sync(&mut self, set: bool) {
-        self.fdflag(libc::__WASI_FDFLAG_SYNC, set);
+        self.fdflag(wasi::FDFLAG_SYNC, set);
     }
 
-    fn fdflag(&mut self, bit: libc::__wasi_fdflags_t, set: bool) {
+    fn fdflag(&mut self, bit: wasi::FdFlags, set: bool) {
         if set {
             self.fdflags |= bit;
         } else {
@@ -314,15 +310,15 @@
         }
     }
 
-    pub fn fs_rights_base(&mut self, rights: libc::__wasi_rights_t) {
+    pub fn fs_rights_base(&mut self, rights: wasi::Rights) {
         self.rights_base = Some(rights);
     }
 
-    pub fn fs_rights_inheriting(&mut self, rights: libc::__wasi_rights_t) {
+    pub fn fs_rights_inheriting(&mut self, rights: wasi::Rights) {
         self.rights_inheriting = Some(rights);
     }
 
-    fn rights_base(&self) -> libc::__wasi_rights_t {
+    fn rights_base(&self) -> wasi::Rights {
         if let Some(rights) = self.rights_base {
             return rights;
         }
@@ -334,52 +330,52 @@
         // based on that.
         let mut base = 0;
         if self.read {
-            base |= libc::__WASI_RIGHT_FD_READ;
-            base |= libc::__WASI_RIGHT_FD_READDIR;
+            base |= wasi::RIGHT_FD_READ;
+            base |= wasi::RIGHT_FD_READDIR;
         }
         if self.write {
-            base |= libc::__WASI_RIGHT_FD_WRITE;
-            base |= libc::__WASI_RIGHT_FD_DATASYNC;
-            base |= libc::__WASI_RIGHT_FD_ALLOCATE;
-            base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_SIZE;
+            base |= wasi::RIGHT_FD_WRITE;
+            base |= wasi::RIGHT_FD_DATASYNC;
+            base |= wasi::RIGHT_FD_ALLOCATE;
+            base |= wasi::RIGHT_FD_FILESTAT_SET_SIZE;
         }
 
         // FIXME: some of these should probably be read-only or write-only...
-        base |= libc::__WASI_RIGHT_FD_ADVISE;
-        base |= libc::__WASI_RIGHT_FD_FDSTAT_SET_FLAGS;
-        base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_TIMES;
-        base |= libc::__WASI_RIGHT_FD_SEEK;
-        base |= libc::__WASI_RIGHT_FD_SYNC;
-        base |= libc::__WASI_RIGHT_FD_TELL;
-        base |= libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY;
-        base |= libc::__WASI_RIGHT_PATH_CREATE_FILE;
-        base |= libc::__WASI_RIGHT_PATH_FILESTAT_GET;
-        base |= libc::__WASI_RIGHT_PATH_LINK_SOURCE;
-        base |= libc::__WASI_RIGHT_PATH_LINK_TARGET;
-        base |= libc::__WASI_RIGHT_PATH_OPEN;
-        base |= libc::__WASI_RIGHT_PATH_READLINK;
-        base |= libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY;
-        base |= libc::__WASI_RIGHT_PATH_RENAME_SOURCE;
-        base |= libc::__WASI_RIGHT_PATH_RENAME_TARGET;
-        base |= libc::__WASI_RIGHT_PATH_SYMLINK;
-        base |= libc::__WASI_RIGHT_PATH_UNLINK_FILE;
-        base |= libc::__WASI_RIGHT_POLL_FD_READWRITE;
+        base |= wasi::RIGHT_FD_ADVISE;
+        base |= wasi::RIGHT_FD_FDSTAT_SET_FLAGS;
+        base |= wasi::RIGHT_FD_FILESTAT_SET_TIMES;
+        base |= wasi::RIGHT_FD_SEEK;
+        base |= wasi::RIGHT_FD_SYNC;
+        base |= wasi::RIGHT_FD_TELL;
+        base |= wasi::RIGHT_PATH_CREATE_DIRECTORY;
+        base |= wasi::RIGHT_PATH_CREATE_FILE;
+        base |= wasi::RIGHT_PATH_FILESTAT_GET;
+        base |= wasi::RIGHT_PATH_LINK_SOURCE;
+        base |= wasi::RIGHT_PATH_LINK_TARGET;
+        base |= wasi::RIGHT_PATH_OPEN;
+        base |= wasi::RIGHT_PATH_READLINK;
+        base |= wasi::RIGHT_PATH_REMOVE_DIRECTORY;
+        base |= wasi::RIGHT_PATH_RENAME_SOURCE;
+        base |= wasi::RIGHT_PATH_RENAME_TARGET;
+        base |= wasi::RIGHT_PATH_SYMLINK;
+        base |= wasi::RIGHT_PATH_UNLINK_FILE;
+        base |= wasi::RIGHT_POLL_FD_READWRITE;
 
         return base;
     }
 
-    fn rights_inheriting(&self) -> libc::__wasi_rights_t {
+    fn rights_inheriting(&self) -> wasi::Rights {
         self.rights_inheriting.unwrap_or_else(|| self.rights_base())
     }
 
-    pub fn lookup_flags(&mut self, flags: libc::__wasi_lookupflags_t) {
+    pub fn lookup_flags(&mut self, flags: wasi::LookupFlags) {
         self.dirflags = flags;
     }
 }
 
 impl File {
     pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
-        let (dir, file) = open_parent(path, libc::__WASI_RIGHT_PATH_OPEN)?;
+        let (dir, file) = open_parent(path, wasi::RIGHT_PATH_OPEN)?;
         open_at(&dir, &file, opts)
     }
 
@@ -388,14 +384,12 @@
     }
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
-        let mut ret = FileAttr::zero();
-        self.fd.filestat_get(&mut ret.meta)?;
-        Ok(ret)
+        self.fd.filestat_get().map(|meta| FileAttr { meta })
     }
 
     pub fn metadata_at(
         &self,
-        flags: libc::__wasi_lookupflags_t,
+        flags: wasi::LookupFlags,
         path: &Path,
     ) -> io::Result<FileAttr> {
         metadata_at(&self.fd, flags, path)
@@ -477,7 +471,7 @@
     }
 
     pub fn mkdir(&self, p: &Path) -> io::Result<()> {
-        let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY)?;
+        let (dir, file) = open_parent(p, wasi::RIGHT_PATH_CREATE_DIRECTORY)?;
         dir.create_directory(file.as_os_str().as_bytes())
     }
 }
@@ -508,13 +502,13 @@
 }
 
 pub fn unlink(p: &Path) -> io::Result<()> {
-    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_UNLINK_FILE)?;
+    let (dir, file) = open_parent(p, wasi::RIGHT_PATH_UNLINK_FILE)?;
     dir.unlink_file(file.as_os_str().as_bytes())
 }
 
 pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
-    let (old, old_file) = open_parent(old, libc::__WASI_RIGHT_PATH_RENAME_SOURCE)?;
-    let (new, new_file) = open_parent(new, libc::__WASI_RIGHT_PATH_RENAME_TARGET)?;
+    let (old, old_file) = open_parent(old, wasi::RIGHT_PATH_RENAME_SOURCE)?;
+    let (new, new_file) = open_parent(new, wasi::RIGHT_PATH_RENAME_TARGET)?;
     old.rename(
         old_file.as_os_str().as_bytes(),
         &new,
@@ -529,12 +523,12 @@
 }
 
 pub fn rmdir(p: &Path) -> io::Result<()> {
-    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY)?;
+    let (dir, file) = open_parent(p, wasi::RIGHT_PATH_REMOVE_DIRECTORY)?;
     dir.remove_directory(file.as_os_str().as_bytes())
 }
 
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
-    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_READLINK)?;
+    let (dir, file) = open_parent(p, wasi::RIGHT_PATH_READLINK)?;
     read_link(&dir, &file)
 }
 
@@ -570,15 +564,15 @@
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_SYMLINK)?;
+    let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_SYMLINK)?;
     dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes())
 }
 
 pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
-    let (src, src_file) = open_parent(src, libc::__WASI_RIGHT_PATH_LINK_SOURCE)?;
-    let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_LINK_TARGET)?;
+    let (src, src_file) = open_parent(src, wasi::RIGHT_PATH_LINK_SOURCE)?;
+    let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_LINK_TARGET)?;
     src.link(
-        libc::__WASI_LOOKUP_SYMLINK_FOLLOW,
+        wasi::LOOKUP_SYMLINK_FOLLOW,
         src_file.as_os_str().as_bytes(),
         &dst,
         dst_file.as_os_str().as_bytes(),
@@ -586,23 +580,22 @@
 }
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
-    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
-    metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, &file)
+    let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?;
+    metadata_at(&dir, wasi::LOOKUP_SYMLINK_FOLLOW, &file)
 }
 
 pub fn lstat(p: &Path) -> io::Result<FileAttr> {
-    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
+    let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?;
     metadata_at(&dir, 0, &file)
 }
 
 fn metadata_at(
     fd: &WasiFd,
-    flags: libc::__wasi_lookupflags_t,
+    flags: wasi::LookupFlags,
     path: &Path,
 ) -> io::Result<FileAttr> {
-    let mut ret = FileAttr::zero();
-    fd.path_filestat_get(flags, path.as_os_str().as_bytes(), &mut ret.meta)?;
-    Ok(ret)
+    fd.path_filestat_get(flags, path.as_os_str().as_bytes())
+        .map(|meta| FileAttr { meta })
 }
 
 pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
@@ -652,12 +645,12 @@
 /// to any preopened file descriptor.
 fn open_parent(
     p: &Path,
-    rights: libc::__wasi_rights_t,
+    rights: wasi::Rights,
 ) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
     let p = CString::new(p.as_os_str().as_bytes())?;
     unsafe {
         let mut ret = ptr::null();
-        let fd = __wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret);
+        let fd = libc::__wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret);
         if fd == -1 {
             let msg = format!(
                 "failed to find a preopened file descriptor \
@@ -677,15 +670,4 @@
 
         return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path));
     }
-
-    // FIXME(rust-lang/libc#1314) use the `libc` crate for this when the API
-    // there is published
-    extern "C" {
-        pub fn __wasilibc_find_relpath(
-            path: *const libc::c_char,
-            rights_base: libc::__wasi_rights_t,
-            rights_inheriting: libc::__wasi_rights_t,
-            relative_path: *mut *const libc::c_char,
-        ) -> libc::c_int;
-    }
 }
diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs
index ffecca5..4be92fa 100644
--- a/src/libstd/sys/wasi/io.rs
+++ b/src/libstd/sys/wasi/io.rs
@@ -1,11 +1,12 @@
 use crate::marker::PhantomData;
 use crate::slice;
 
-use libc::{__wasi_ciovec_t, __wasi_iovec_t, c_void};
+use ::wasi::wasi_unstable as wasi;
+use core::ffi::c_void;
 
 #[repr(transparent)]
 pub struct IoSlice<'a> {
-    vec: __wasi_ciovec_t,
+    vec: wasi::CIoVec,
     _p: PhantomData<&'a [u8]>,
 }
 
@@ -13,7 +14,7 @@
     #[inline]
     pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
         IoSlice {
-            vec: __wasi_ciovec_t {
+            vec: wasi::CIoVec {
                 buf: buf.as_ptr() as *const c_void,
                 buf_len: buf.len(),
             },
@@ -43,7 +44,7 @@
 
 #[repr(transparent)]
 pub struct IoSliceMut<'a> {
-    vec: __wasi_iovec_t,
+    vec: wasi::IoVec,
     _p: PhantomData<&'a mut [u8]>,
 }
 
@@ -51,7 +52,7 @@
     #[inline]
     pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
         IoSliceMut {
-            vec: __wasi_iovec_t {
+            vec: wasi::IoVec {
                 buf: buf.as_mut_ptr() as *mut c_void,
                 buf_len: buf.len()
             },
diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs
index 57da81b..517e3be 100644
--- a/src/libstd/sys/wasi/mod.rs
+++ b/src/libstd/sys/wasi/mod.rs
@@ -14,10 +14,10 @@
 //! compiling for wasm. That way it's a compile time error for something that's
 //! guaranteed to be a runtime error!
 
-use libc;
-use crate::io::{Error, ErrorKind};
+use crate::io as std_io;
 use crate::mem;
 use crate::os::raw::c_char;
+use ::wasi::wasi_unstable as wasi;
 
 pub mod alloc;
 pub mod args;
@@ -56,31 +56,42 @@
 pub fn init() {
 }
 
-pub fn unsupported<T>() -> crate::io::Result<T> {
+pub fn unsupported<T>() -> std_io::Result<T> {
     Err(unsupported_err())
 }
 
-pub fn unsupported_err() -> Error {
-    Error::new(ErrorKind::Other, "operation not supported on wasm yet")
+pub fn unsupported_err() -> std_io::Error {
+    std_io::Error::new(
+        std_io::ErrorKind::Other,
+        "operation not supported on wasm yet",
+    )
 }
 
-pub fn decode_error_kind(errno: i32) -> ErrorKind {
-    match errno as libc::c_int {
-        libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
-        libc::ECONNRESET => ErrorKind::ConnectionReset,
-        libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
-        libc::EPIPE => ErrorKind::BrokenPipe,
-        libc::ENOTCONN => ErrorKind::NotConnected,
-        libc::ECONNABORTED => ErrorKind::ConnectionAborted,
-        libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
-        libc::EADDRINUSE => ErrorKind::AddrInUse,
-        libc::ENOENT => ErrorKind::NotFound,
-        libc::EINTR => ErrorKind::Interrupted,
-        libc::EINVAL => ErrorKind::InvalidInput,
-        libc::ETIMEDOUT => ErrorKind::TimedOut,
-        libc::EEXIST => ErrorKind::AlreadyExists,
-        libc::EAGAIN => ErrorKind::WouldBlock,
-        _ => ErrorKind::Other,
+pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
+    use std_io::ErrorKind::*;
+    if errno > u16::max_value() as i32 || errno < 0 {
+        return Other;
+    }
+    let code = match wasi::Error::new(errno as u16) {
+        Some(code) => code,
+        None => return Other,
+    };
+    match code {
+        wasi::ECONNREFUSED => ConnectionRefused,
+        wasi::ECONNRESET => ConnectionReset,
+        wasi::EPERM | wasi::EACCES => PermissionDenied,
+        wasi::EPIPE => BrokenPipe,
+        wasi::ENOTCONN => NotConnected,
+        wasi::ECONNABORTED => ConnectionAborted,
+        wasi::EADDRNOTAVAIL => AddrNotAvailable,
+        wasi::EADDRINUSE => AddrInUse,
+        wasi::ENOENT => NotFound,
+        wasi::EINTR => Interrupted,
+        wasi::EINVAL => InvalidInput,
+        wasi::ETIMEDOUT => TimedOut,
+        wasi::EEXIST => AlreadyExists,
+        wasi::EAGAIN => WouldBlock,
+        _ => Other,
     }
 }
 
@@ -105,40 +116,16 @@
 pub fn hashmap_random_keys() -> (u64, u64) {
     let mut ret = (0u64, 0u64);
     unsafe {
-        let base = &mut ret as *mut (u64, u64) as *mut libc::c_void;
+        let base = &mut ret as *mut (u64, u64) as *mut core::ffi::c_void;
         let len = mem::size_of_val(&ret);
-        cvt_wasi(libc::__wasi_random_get(base, len)).unwrap();
+        let ret = wasi::raw::__wasi_random_get(base, len);
+        if ret != 0 {
+            panic!("__wasi_random_get failure")
+        }
     }
     return ret
 }
 
-#[doc(hidden)]
-pub trait IsMinusOne {
-    fn is_minus_one(&self) -> bool;
-}
-
-macro_rules! impl_is_minus_one {
-    ($($t:ident)*) => ($(impl IsMinusOne for $t {
-        fn is_minus_one(&self) -> bool {
-            *self == -1
-        }
-    })*)
-}
-
-impl_is_minus_one! { i8 i16 i32 i64 isize }
-
-pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
-    if t.is_minus_one() {
-        Err(Error::last_os_error())
-    } else {
-        Ok(t)
-    }
-}
-
-pub fn cvt_wasi(r: u16) -> crate::io::Result<()> {
-    if r != libc::__WASI_ESUCCESS {
-        Err(Error::from_raw_os_error(r as i32))
-    } else {
-        Ok(())
-    }
+fn err2io(err: wasi::Error) -> std_io::Error {
+    std_io::Error::from_raw_os_error(err.get() as i32)
 }
diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs
index 822ea02..feee840 100644
--- a/src/libstd/sys/wasi/os.rs
+++ b/src/libstd/sys/wasi/os.rs
@@ -9,7 +9,7 @@
 use crate::ptr;
 use crate::str;
 use crate::sys::memchr;
-use crate::sys::{cvt, unsupported, Void};
+use crate::sys::{unsupported, Void};
 use crate::vec;
 
 #[cfg(not(target_feature = "atomics"))]
@@ -28,16 +28,11 @@
 }
 
 pub fn error_string(errno: i32) -> String {
-    extern {
-        fn strerror_r(errnum: libc::c_int, buf: *mut libc::c_char,
-                      buflen: libc::size_t) -> libc::c_int;
-    }
-
     let mut buf = [0 as libc::c_char; 1024];
 
     let p = buf.as_mut_ptr();
     unsafe {
-        if strerror_r(errno as libc::c_int, p, buf.len()) < 0 {
+        if libc::strerror_r(errno as libc::c_int, p, buf.len()) < 0 {
             panic!("strerror_r failure");
         }
         str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
@@ -89,7 +84,6 @@
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
-
 pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
     _dont_send_or_sync_me: PhantomData<*mut ()>,
@@ -182,3 +176,26 @@
 pub fn getpid() -> u32 {
     panic!("unsupported");
 }
+
+#[doc(hidden)]
+pub trait IsMinusOne {
+    fn is_minus_one(&self) -> bool;
+}
+
+macro_rules! impl_is_minus_one {
+    ($($t:ident)*) => ($(impl IsMinusOne for $t {
+        fn is_minus_one(&self) -> bool {
+            *self == -1
+        }
+    })*)
+}
+
+impl_is_minus_one! { i8 i16 i32 i64 isize }
+
+fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
+    if t.is_minus_one() {
+        Err(io::Error::last_os_error())
+    } else {
+        Ok(t)
+    }
+}
diff --git a/src/libstd/sys/wasi/process.rs b/src/libstd/sys/wasi/process.rs
index 788b829..1c4d028 100644
--- a/src/libstd/sys/wasi/process.rs
+++ b/src/libstd/sys/wasi/process.rs
@@ -4,14 +4,16 @@
 use crate::sys::fs::File;
 use crate::sys::pipe::AnonPipe;
 use crate::sys::{unsupported, Void};
-use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::sys_common::process::CommandEnv;
+
+pub use crate::ffi::OsString as EnvKey;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct Command {
-    env: CommandEnv<DefaultEnvKey>
+    env: CommandEnv
 }
 
 // passed back to std::process with the pipes connected to the child, if any
@@ -38,7 +40,7 @@
     pub fn arg(&mut self, _arg: &OsStr) {
     }
 
-    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+    pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
     }
 
diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs
index 2bf8d80..1d57b99 100644
--- a/src/libstd/sys/wasi/stdio.rs
+++ b/src/libstd/sys/wasi/stdio.rs
@@ -1,8 +1,9 @@
 use crate::io::{self, IoSlice, IoSliceMut};
-use crate::libc;
 use crate::mem::ManuallyDrop;
 use crate::sys::fd::WasiFd;
 
+use ::wasi::wasi_unstable as wasi;
+
 pub struct Stdin;
 pub struct Stdout;
 pub struct Stderr;
@@ -17,7 +18,7 @@
     }
 
     pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) })
+        ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDIN_FD) })
             .read(data)
     }
 }
@@ -32,7 +33,7 @@
     }
 
     pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
-        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDOUT_FILENO as u32) })
+        ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDOUT_FD) })
             .write(data)
     }
 
@@ -51,7 +52,7 @@
     }
 
     pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
-        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDERR_FILENO as u32) })
+        ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDERR_FD) })
             .write(data)
     }
 
@@ -73,7 +74,7 @@
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 pub fn is_ebadf(err: &io::Error) -> bool {
-    err.raw_os_error() == Some(libc::__WASI_EBADF as i32)
+    err.raw_os_error() == Some(wasi::EBADF.get() as i32)
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs
index 5e69e4d..28a504f 100644
--- a/src/libstd/sys/wasi/thread.rs
+++ b/src/libstd/sys/wasi/thread.rs
@@ -1,10 +1,10 @@
-use crate::cmp;
 use crate::ffi::CStr;
 use crate::io;
-use crate::sys::cvt;
+use crate::mem;
 use crate::sys::{unsupported, Void};
 use crate::time::Duration;
-use libc;
+
+use ::wasi::wasi_unstable as wasi;
 
 pub struct Thread(Void);
 
@@ -19,8 +19,8 @@
     }
 
     pub fn yield_now() {
-        let ret = unsafe { libc::__wasi_sched_yield() };
-        debug_assert_eq!(ret, 0);
+        let ret = wasi::sched_yield();
+        debug_assert_eq!(ret, Ok(()));
     }
 
     pub fn set_name(_name: &CStr) {
@@ -28,19 +28,37 @@
     }
 
     pub fn sleep(dur: Duration) {
-        let mut secs = dur.as_secs();
-        let mut nsecs = dur.subsec_nanos() as i32;
+        let nanos = dur.as_nanos();
+        assert!(nanos <= u64::max_value() as u128);
 
-        unsafe {
-            while secs > 0 || nsecs > 0 {
-                let mut ts = libc::timespec {
-                    tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
-                    tv_nsec: nsecs,
-                };
-                secs -= ts.tv_sec as u64;
-                cvt(libc::nanosleep(&ts, &mut ts)).unwrap();
-                nsecs = 0;
-            }
+        const CLOCK_ID: wasi::Userdata = 0x0123_45678;
+
+        let clock = wasi::raw::__wasi_subscription_u_clock_t {
+            identifier: CLOCK_ID,
+            clock_id: wasi::CLOCK_MONOTONIC,
+            timeout: nanos as u64,
+            precision: 0,
+            flags: 0,
+        };
+
+        let in_ = [wasi::Subscription {
+            userdata: 0,
+            type_: wasi::EVENTTYPE_CLOCK,
+            u: wasi::raw::__wasi_subscription_u { clock: clock },
+        }];
+        let (res, event) = unsafe {
+            let mut out: [wasi::Event; 1] = mem::zeroed();
+            let res = wasi::poll_oneoff(&in_, &mut out);
+            (res, out[0])
+        };
+        match (res, event) {
+            (Ok(1), wasi::Event {
+                userdata: CLOCK_ID,
+                error: 0,
+                type_: wasi::EVENTTYPE_CLOCK,
+                ..
+            }) => {}
+            _ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
         }
     }
 
diff --git a/src/libstd/sys/wasi/time.rs b/src/libstd/sys/wasi/time.rs
index 3f14c80..4394a22 100644
--- a/src/libstd/sys/wasi/time.rs
+++ b/src/libstd/sys/wasi/time.rs
@@ -1,7 +1,5 @@
 use crate::time::Duration;
-use crate::mem;
-use crate::sys::cvt_wasi;
-use libc;
+use ::wasi::wasi_unstable as wasi;
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
 pub struct Instant(Duration);
@@ -12,23 +10,19 @@
 pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
 
 fn current_time(clock: u32) -> Duration {
-    unsafe {
-        let mut ts = mem::zeroed();
-        cvt_wasi(libc::__wasi_clock_time_get(
-            clock,
-            1, // precision... seems ignored though?
-            &mut ts,
-        )).unwrap();
-        Duration::new(
-            (ts / 1_000_000_000) as u64,
-            (ts % 1_000_000_000) as u32,
-        )
-    }
+    let ts = wasi::clock_time_get(
+        clock,
+        1, // precision... seems ignored though?
+    ).unwrap();
+    Duration::new(
+        (ts / 1_000_000_000) as u64,
+        (ts % 1_000_000_000) as u32,
+    )
 }
 
 impl Instant {
     pub fn now() -> Instant {
-        Instant(current_time(libc::__WASI_CLOCK_MONOTONIC))
+        Instant(current_time(wasi::CLOCK_MONOTONIC))
     }
 
     pub const fn zero() -> Instant {
@@ -54,10 +48,10 @@
 
 impl SystemTime {
     pub fn now() -> SystemTime {
-        SystemTime(current_time(libc::__WASI_CLOCK_REALTIME))
+        SystemTime(current_time(wasi::CLOCK_REALTIME))
     }
 
-    pub fn from_wasi_timestamp(ts: libc::__wasi_timestamp_t) -> SystemTime {
+    pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
         SystemTime(Duration::from_nanos(ts))
     }
 
diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs
index a02e009..edf933d 100644
--- a/src/libstd/sys/wasm/process.rs
+++ b/src/libstd/sys/wasm/process.rs
@@ -4,14 +4,16 @@
 use crate::sys::fs::File;
 use crate::sys::pipe::AnonPipe;
 use crate::sys::{unsupported, Void};
-use crate::sys_common::process::{CommandEnv, DefaultEnvKey};
+use crate::sys_common::process::CommandEnv;
+
+pub use crate::ffi::OsString as EnvKey;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct Command {
-    env: CommandEnv<DefaultEnvKey>
+    env: CommandEnv,
 }
 
 // passed back to std::process with the pipes connected to the child, if any
@@ -38,7 +40,7 @@
     pub fn arg(&mut self, _arg: &OsStr) {
     }
 
-    pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
+    pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
     }
 
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 05e0ca6..8658deb 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -19,7 +19,7 @@
 use crate::sys::stdio;
 use crate::sys::cvt;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
-use crate::sys_common::process::{CommandEnv, EnvKey};
+use crate::sys_common::process::CommandEnv;
 use crate::borrow::Borrow;
 
 use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE};
@@ -30,30 +30,28 @@
 
 #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
 #[doc(hidden)]
-pub struct WindowsEnvKey(OsString);
+pub struct EnvKey(OsString);
 
-impl From<OsString> for WindowsEnvKey {
+impl From<OsString> for EnvKey {
     fn from(k: OsString) -> Self {
         let mut buf = k.into_inner().into_inner();
         buf.make_ascii_uppercase();
-        WindowsEnvKey(FromInner::from_inner(FromInner::from_inner(buf)))
+        EnvKey(FromInner::from_inner(FromInner::from_inner(buf)))
     }
 }
 
-impl From<WindowsEnvKey> for OsString {
-    fn from(k: WindowsEnvKey) -> Self { k.0 }
+impl From<EnvKey> for OsString {
+    fn from(k: EnvKey) -> Self { k.0 }
 }
 
-impl Borrow<OsStr> for WindowsEnvKey {
+impl Borrow<OsStr> for EnvKey {
     fn borrow(&self) -> &OsStr { &self.0 }
 }
 
-impl AsRef<OsStr> for WindowsEnvKey {
+impl AsRef<OsStr> for EnvKey {
     fn as_ref(&self) -> &OsStr { &self.0 }
 }
 
-impl EnvKey for WindowsEnvKey {}
-
 
 fn ensure_no_nuls<T: AsRef<OsStr>>(str: T) -> io::Result<T> {
     if str.as_ref().encode_wide().any(|b| b == 0) {
@@ -66,7 +64,7 @@
 pub struct Command {
     program: OsString,
     args: Vec<OsString>,
-    env: CommandEnv<WindowsEnvKey>,
+    env: CommandEnv,
     cwd: Option<OsString>,
     flags: u32,
     detach: bool, // not currently exposed in std::process
@@ -110,7 +108,7 @@
     pub fn arg(&mut self, arg: &OsStr) {
         self.args.push(arg.to_os_string())
     }
-    pub fn env_mut(&mut self) -> &mut CommandEnv<WindowsEnvKey> {
+    pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
     }
     pub fn cwd(&mut self, dir: &OsStr) {
@@ -498,7 +496,7 @@
     }
 }
 
-fn make_envp(maybe_env: Option<BTreeMap<WindowsEnvKey, OsString>>)
+fn make_envp(maybe_env: Option<BTreeMap<EnvKey, OsString>>)
              -> io::Result<(*mut c_void, Vec<u16>)> {
     // On Windows we pass an "environment block" which is not a char**, but
     // rather a concatenation of null-terminated k=v\0 sequences, with a final
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index bf37ff7..01711d4 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -2,25 +2,38 @@
 /// supported platforms.
 
 use crate::env;
+use crate::fmt;
 use crate::io;
+use crate::borrow::Cow;
 use crate::io::prelude::*;
-use crate::mem;
-use crate::path::{self, Path};
-use crate::ptr;
-use crate::sync::atomic::{self, Ordering};
+use crate::path::{self, Path, PathBuf};
 use crate::sys::mutex::Mutex;
 
-use backtrace::{BytesOrWideString, Frame, Symbol};
-
-pub const HEX_WIDTH: usize = 2 + 2 * mem::size_of::<usize>();
+use backtrace_rs::{BacktraceFmt, BytesOrWideString, PrintFmt};
 
 /// Max number of frames to print.
 const MAX_NB_FRAMES: usize = 100;
 
-/// Prints the current backtrace.
-pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> {
+pub fn lock() -> impl Drop {
+    struct Guard;
     static LOCK: Mutex = Mutex::new();
 
+    impl Drop for Guard {
+        fn drop(&mut self) {
+            unsafe {
+                LOCK.unlock();
+            }
+        }
+    }
+
+    unsafe {
+        LOCK.lock();
+        return Guard;
+    }
+}
+
+/// Prints the current backtrace.
+pub fn print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> {
     // There are issues currently linking libbacktrace into tests, and in
     // general during libstd's own unit tests we're not testing this path. In
     // test mode immediately return here to optimize away any references to the
@@ -32,33 +45,69 @@
     // Use a lock to prevent mixed output in multithreading context.
     // Some platforms also requires it, like `SymFromAddr` on Windows.
     unsafe {
-        LOCK.lock();
-        let res = _print(w, format);
-        LOCK.unlock();
-        res
+        let _lock = lock();
+        _print(w, format)
     }
 }
 
-fn _print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> {
-    writeln!(w, "stack backtrace:")?;
-
-    let mut printer = Printer::new(format, w);
-    unsafe {
-        backtrace::trace_unsynchronized(|frame| {
-            let mut hit = false;
-            backtrace::resolve_frame_unsynchronized(frame, |symbol| {
-                hit = true;
-                printer.output(frame, Some(symbol));
-            });
-            if !hit {
-                printer.output(frame, None);
-            }
-            !printer.done
-        });
+unsafe fn _print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> {
+    struct DisplayBacktrace {
+        format: PrintFmt,
     }
-    if printer.skipped {
+    impl fmt::Display for DisplayBacktrace {
+        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+            unsafe {
+                _print_fmt(fmt, self.format)
+            }
+        }
+    }
+    write!(w, "{}", DisplayBacktrace { format })
+}
+
+unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::Result {
+    let cwd = env::current_dir().ok();
+    let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| {
+        output_filename(fmt, bows, print_fmt, cwd.as_ref())
+    };
+    let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path);
+    bt_fmt.add_context()?;
+    let mut idx = 0;
+    let mut res = Ok(());
+    backtrace_rs::trace_unsynchronized(|frame| {
+        if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
+            return false;
+        }
+
+        let mut hit = false;
+        let mut stop = false;
+        backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
+            hit = true;
+            if print_fmt == PrintFmt::Short {
+                if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
+                    if sym.contains("__rust_begin_short_backtrace") {
+                        stop = true;
+                        return;
+                    }
+                }
+            }
+
+            res = bt_fmt.frame().symbol(frame, symbol);
+        });
+        if stop {
+            return false;
+        }
+        if !hit {
+            res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
+        }
+
+        idx += 1;
+        res.is_ok()
+    });
+    res?;
+    bt_fmt.finish()?;
+    if print_fmt == PrintFmt::Short {
         writeln!(
-            w,
+            fmt,
             "note: Some details are omitted, \
              run with `RUST_BACKTRACE=full` for a verbose backtrace."
         )?;
@@ -77,33 +126,32 @@
     f()
 }
 
-/// Controls how the backtrace should be formatted.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum PrintFormat {
-    /// Show only relevant data from the backtrace.
-    Short = 2,
-    /// Show all the frames with absolute path for files.
-    Full = 3,
-}
-
 // For now logging is turned off by default, and this function checks to see
 // whether the magical environment variable is present to see if it's turned on.
-pub fn log_enabled() -> Option<PrintFormat> {
+pub fn log_enabled() -> Option<PrintFmt> {
+    use crate::sync::atomic::{self, Ordering};
+
+    // Setting environment variables for Fuchsia components isn't a standard
+    // or easily supported workflow. For now, always display backtraces.
+    if cfg!(target_os = "fuchsia") {
+        return Some(PrintFmt::Full);
+    }
+
     static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0);
     match ENABLED.load(Ordering::SeqCst) {
         0 => {}
         1 => return None,
-        2 => return Some(PrintFormat::Short),
-        _ => return Some(PrintFormat::Full),
+        2 => return Some(PrintFmt::Short),
+        _ => return Some(PrintFmt::Full),
     }
 
     let val = env::var_os("RUST_BACKTRACE").and_then(|x| {
         if &x == "0" {
             None
         } else if &x == "full" {
-            Some(PrintFormat::Full)
+            Some(PrintFmt::Full)
         } else {
-            Some(PrintFormat::Short)
+            Some(PrintFmt::Short)
         }
     });
     ENABLED.store(
@@ -116,130 +164,43 @@
     val
 }
 
-struct Printer<'a, 'b> {
-    format: PrintFormat,
-    done: bool,
-    skipped: bool,
-    idx: usize,
-    out: &'a mut (dyn Write + 'b),
-}
-
-impl<'a, 'b> Printer<'a, 'b> {
-    fn new(format: PrintFormat, out: &'a mut (dyn Write + 'b)) -> Printer<'a, 'b> {
-        Printer { format, done: false, skipped: false, idx: 0, out }
-    }
-
-    /// Prints the symbol of the backtrace frame.
-    ///
-    /// These output functions should now be used everywhere to ensure consistency.
-    /// You may want to also use `output_fileline`.
-    fn output(&mut self, frame: &Frame, symbol: Option<&Symbol>) {
-        if self.idx > MAX_NB_FRAMES {
-            self.done = true;
-            self.skipped = true;
-            return;
+/// Prints the filename of the backtrace frame.
+///
+/// See also `output`.
+pub fn output_filename(
+    fmt: &mut fmt::Formatter<'_>,
+    bows: BytesOrWideString<'_>,
+    print_fmt: PrintFmt,
+    cwd: Option<&PathBuf>,
+) -> fmt::Result {
+    let file: Cow<'_, Path> = match bows {
+        #[cfg(unix)]
+        BytesOrWideString::Bytes(bytes) => {
+            use crate::os::unix::prelude::*;
+            Path::new(crate::ffi::OsStr::from_bytes(bytes)).into()
         }
-        if self._output(frame, symbol).is_err() {
-            self.done = true;
+        #[cfg(not(unix))]
+        BytesOrWideString::Bytes(bytes) => {
+            Path::new(crate::str::from_utf8(bytes).unwrap_or("<unknown>")).into()
         }
-        self.idx += 1;
-    }
-
-    fn _output(&mut self, frame: &Frame, symbol: Option<&Symbol>) -> io::Result<()> {
-        if self.format == PrintFormat::Short {
-            if let Some(sym) = symbol.and_then(|s| s.name()).and_then(|s| s.as_str()) {
-                if sym.contains("__rust_begin_short_backtrace") {
-                    self.skipped = true;
-                    self.done = true;
-                    return Ok(());
-                }
-            }
-
-            // Remove the `17: 0x0 - <unknown>` line.
-            if self.format == PrintFormat::Short && frame.ip() == ptr::null_mut() {
-                self.skipped = true;
-                return Ok(());
-            }
-        }
-
-        match self.format {
-            PrintFormat::Full => {
-                write!(self.out, "  {:2}: {:2$?} - ", self.idx, frame.ip(), HEX_WIDTH)?
-            }
-            PrintFormat::Short => write!(self.out, "  {:2}: ", self.idx)?,
-        }
-
-        match symbol.and_then(|s| s.name()) {
-            Some(symbol) => {
-                match self.format {
-                    PrintFormat::Full => write!(self.out, "{}", symbol)?,
-                    // Strip the trailing hash if short mode.
-                    PrintFormat::Short => write!(self.out, "{:#}", symbol)?,
-                }
-            }
-            None => self.out.write_all(b"<unknown>")?,
-        }
-        self.out.write_all(b"\n")?;
-        if let Some(sym) = symbol {
-            self.output_fileline(sym)?;
-        }
-        Ok(())
-    }
-
-    /// Prints the filename and line number of the backtrace frame.
-    ///
-    /// See also `output`.
-    fn output_fileline(&mut self, symbol: &Symbol) -> io::Result<()> {
         #[cfg(windows)]
-        let path_buf;
-        let file = match symbol.filename_raw() {
-            #[cfg(unix)]
-            Some(BytesOrWideString::Bytes(bytes)) => {
-                use crate::os::unix::prelude::*;
-                Path::new(crate::ffi::OsStr::from_bytes(bytes))
-            }
-            #[cfg(not(unix))]
-            Some(BytesOrWideString::Bytes(bytes)) => {
-                Path::new(crate::str::from_utf8(bytes).unwrap_or("<unknown>"))
-            }
-            #[cfg(windows)]
-            Some(BytesOrWideString::Wide(wide)) => {
-                use crate::os::windows::prelude::*;
-                path_buf = crate::ffi::OsString::from_wide(wide);
-                Path::new(&path_buf)
-            }
-            #[cfg(not(windows))]
-            Some(BytesOrWideString::Wide(_wide)) => {
-                Path::new("<unknown>")
-            }
-            None => return Ok(()),
-        };
-        let line = match symbol.lineno() {
-            Some(line) => line,
-            None => return Ok(()),
-        };
-        // prior line: "  ##: {:2$} - func"
-        self.out.write_all(b"")?;
-        match self.format {
-            PrintFormat::Full => write!(self.out, "           {:1$}", "", HEX_WIDTH)?,
-            PrintFormat::Short => write!(self.out, "           ")?,
+        BytesOrWideString::Wide(wide) => {
+            use crate::os::windows::prelude::*;
+            Cow::Owned(crate::ffi::OsString::from_wide(wide).into())
         }
-
-        let mut already_printed = false;
-        if self.format == PrintFormat::Short && file.is_absolute() {
-            if let Ok(cwd) = env::current_dir() {
-                if let Ok(stripped) = file.strip_prefix(&cwd) {
-                    if let Some(s) = stripped.to_str() {
-                        write!(self.out, "  at .{}{}:{}", path::MAIN_SEPARATOR, s, line)?;
-                        already_printed = true;
-                    }
+        #[cfg(not(windows))]
+        BytesOrWideString::Wide(_wide) => {
+            Path::new("<unknown>").into()
+        }
+    };
+    if print_fmt == PrintFmt::Short && file.is_absolute() {
+        if let Some(cwd) = cwd {
+            if let Ok(stripped) = file.strip_prefix(&cwd) {
+                if let Some(s) = stripped.to_str() {
+                    return write!(fmt, ".{}{}", path::MAIN_SEPARATOR, s);
                 }
             }
         }
-        if !already_printed {
-            write!(self.out, "  at {}:{}", file.display(), line)?;
-        }
-
-        self.out.write_all(b"\n")
     }
+    fmt::Display::fmt(&file.display(), fmt)
 }
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 9190a3b..cba3eca 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -41,7 +41,6 @@
 
 pub mod alloc;
 pub mod at_exit_imp;
-#[cfg(feature = "backtrace")]
 pub mod backtrace;
 pub mod condvar;
 pub mod io;
diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs
index 4d40dec..bdf66fc 100644
--- a/src/libstd/sys_common/process.rs
+++ b/src/libstd/sys_common/process.rs
@@ -1,47 +1,20 @@
 #![allow(dead_code)]
 #![unstable(feature = "process_internals", issue = "0")]
 
-use crate::ffi::{OsStr, OsString};
-use crate::env;
 use crate::collections::BTreeMap;
-use crate::borrow::Borrow;
-
-pub trait EnvKey:
-    From<OsString> + Into<OsString> +
-    Borrow<OsStr> + Borrow<Self> + AsRef<OsStr> +
-    Ord + Clone {}
-
-// Implement a case-sensitive environment variable key
-#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
-pub struct DefaultEnvKey(OsString);
-
-impl From<OsString> for DefaultEnvKey {
-    fn from(k: OsString) -> Self { DefaultEnvKey(k) }
-}
-
-impl From<DefaultEnvKey> for OsString {
-    fn from(k: DefaultEnvKey) -> Self { k.0 }
-}
-
-impl Borrow<OsStr> for DefaultEnvKey {
-    fn borrow(&self) -> &OsStr { &self.0 }
-}
-
-impl AsRef<OsStr> for DefaultEnvKey {
-    fn as_ref(&self) -> &OsStr { &self.0 }
-}
-
-impl EnvKey for DefaultEnvKey {}
+use crate::env;
+use crate::ffi::{OsStr, OsString};
+use crate::sys::process::EnvKey;
 
 // Stores a set of changes to an environment
 #[derive(Clone, Debug)]
-pub struct CommandEnv<K> {
+pub struct CommandEnv {
     clear: bool,
     saw_path: bool,
-    vars: BTreeMap<K, Option<OsString>>
+    vars: BTreeMap<EnvKey, Option<OsString>>
 }
 
-impl<K: EnvKey> Default for CommandEnv<K> {
+impl Default for CommandEnv {
     fn default() -> Self {
         CommandEnv {
             clear: false,
@@ -51,10 +24,10 @@
     }
 }
 
-impl<K: EnvKey> CommandEnv<K> {
+impl CommandEnv {
     // Capture the current environment with these changes applied
-    pub fn capture(&self) -> BTreeMap<K, OsString> {
-        let mut result = BTreeMap::<K, OsString>::new();
+    pub fn capture(&self) -> BTreeMap<EnvKey, OsString> {
+        let mut result = BTreeMap::<EnvKey, OsString>::new();
         if !self.clear {
             for (k, v) in env::vars_os() {
                 result.insert(k.into(), v);
@@ -90,7 +63,7 @@
         !self.clear && self.vars.is_empty()
     }
 
-    pub fn capture_if_changed(&self) -> Option<BTreeMap<K, OsString>> {
+    pub fn capture_if_changed(&self) -> Option<BTreeMap<EnvKey, OsString>> {
         if self.is_unchanged() {
             None
         } else {
@@ -103,6 +76,7 @@
         self.maybe_saw_path(&key);
         self.vars.insert(key.to_owned().into(), Some(value.to_owned()));
     }
+
     pub fn remove(&mut self, key: &OsStr) {
         self.maybe_saw_path(&key);
         if self.clear {
@@ -111,13 +85,16 @@
             self.vars.insert(key.to_owned().into(), None);
         }
     }
+
     pub fn clear(&mut self) {
         self.clear = true;
         self.vars.clear();
     }
+
     pub fn have_changed_path(&self) -> bool {
         self.saw_path || self.clear
     }
+
     fn maybe_saw_path(&mut self, key: &OsStr) {
         if !self.saw_path && key == "PATH" {
             self.saw_path = true;
diff --git a/src/libstd/tests/env.rs b/src/libstd/tests/env.rs
index 06fb553..f8014cb 100644
--- a/src/libstd/tests/env.rs
+++ b/src/libstd/tests/env.rs
@@ -5,7 +5,7 @@
 use rand::distributions::Alphanumeric;
 
 fn make_rand_name() -> OsString {
-    let mut rng = thread_rng();
+    let rng = thread_rng();
     let n = format!("TEST{}", rng.sample_iter(&Alphanumeric).take(10)
                                  .collect::<String>());
     let n = OsString::from(n);
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 98371b9..3bf2b8b 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -59,6 +59,30 @@
 ///    println!("{}", now.elapsed().as_secs());
 /// }
 /// ```
+///
+/// # Underlying System calls
+/// Currently, the following system calls are being used to get the current time using `now()`:
+///
+/// |  Platform |               System call                                            |
+/// |:---------:|:--------------------------------------------------------------------:|
+/// | Cloud ABI | [clock_time_get (Monotonic Clock)]                                   |
+/// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
+/// | UNIX      | [clock_time_get (Monotonic Clock)]                                   |
+/// | Darwin    | [mach_absolute_time]                                                 |
+/// | VXWorks   | [clock_gettime (Monotonic Clock)]                                    |
+/// | WASI      | [__wasi_clock_time_get (Monotonic Clock)]                            |
+/// | Windows   | [QueryPerformanceCounter]                                            |
+///
+/// [QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
+/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
+/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
+/// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get
+/// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime
+/// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html
+/// [clock_time_get (Monotonic Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt
+///
+/// **Disclaimer:** These system calls might change over time.
+///
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[stable(feature = "time2", since = "1.8.0")]
 pub struct Instant(time::Instant);
@@ -114,6 +138,28 @@
 ///    }
 /// }
 /// ```
+///
+/// # Underlying System calls
+/// Currently, the following system calls are being used to get the current time using `now()`:
+///
+/// |  Platform |               System call                                            |
+/// |:---------:|:--------------------------------------------------------------------:|
+/// | Cloud ABI | [clock_time_get (Realtime Clock)]                                    |
+/// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
+/// | UNIX      | [clock_gettime (Realtime Clock)]                                     |
+/// | DARWIN    | [gettimeofday]                                                       |
+/// | VXWorks   | [clock_gettime (Realtime Clock)]                                     |
+/// | WASI      | [__wasi_clock_time_get (Realtime Clock)]                             |
+/// | Windows   | [GetSystemTimeAsFileTime]                                            |
+///
+/// [clock_time_get (Realtime Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt
+/// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html
+/// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime
+/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get
+/// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime
+///
+/// **Disclaimer:** These system calls might change over time.
+///
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[stable(feature = "time2", since = "1.8.0")]
 pub struct SystemTime(time::SystemTime);
@@ -216,12 +262,11 @@
     }
 
     /// Returns the amount of time elapsed from another instant to this one,
-    /// or None if that instant is earlier than this one.
+    /// or None if that instant is later than this one.
     ///
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(checked_duration_since)]
     /// use std::time::{Duration, Instant};
     /// use std::thread::sleep;
     ///
@@ -231,7 +276,7 @@
     /// println!("{:?}", new_now.checked_duration_since(now));
     /// println!("{:?}", now.checked_duration_since(new_now)); // None
     /// ```
-    #[unstable(feature = "checked_duration_since", issue = "58402")]
+    #[stable(feature = "checked_duration_since", since = "1.39.0")]
     pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
         self.0.checked_sub_instant(&earlier.0)
     }
@@ -242,7 +287,6 @@
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(checked_duration_since)]
     /// use std::time::{Duration, Instant};
     /// use std::thread::sleep;
     ///
@@ -252,7 +296,7 @@
     /// println!("{:?}", new_now.saturating_duration_since(now));
     /// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
     /// ```
-    #[unstable(feature = "checked_duration_since", issue = "58402")]
+    #[stable(feature = "checked_duration_since", since = "1.39.0")]
     pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
         self.checked_duration_since(earlier).unwrap_or(Duration::new(0, 0))
     }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 6be00bc..b634dcc 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -352,7 +352,7 @@
     pub ident: Ident,
     pub attrs: ThinVec<Attribute>,
     pub bounds: GenericBounds,
-
+    pub is_placeholder: bool,
     pub kind: GenericParamKind,
 }
 
@@ -413,11 +413,11 @@
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct WhereBoundPredicate {
     pub span: Span,
-    /// Any generics from a `for` binding
+    /// Any generics from a `for` binding.
     pub bound_generic_params: Vec<GenericParam>,
-    /// The type being bounded
+    /// The type being bounded.
     pub bounded_ty: P<Ty>,
-    /// Trait and lifetime bounds (`Clone+Send+'static`)
+    /// Trait and lifetime bounds (`Clone + Send + 'static`).
     pub bounds: GenericBounds,
 }
 
@@ -495,15 +495,15 @@
     NameValue(Lit),
 }
 
-/// A Block (`{ .. }`).
+/// A block (`{ .. }`).
 ///
 /// E.g., `{ .. }` as in `fn foo() { .. }`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Block {
-    /// Statements in a block
+    /// The statements in the block.
     pub stmts: Vec<Stmt>,
     pub id: NodeId,
-    /// Distinguishes between `unsafe { ... }` and `{ ... }`
+    /// Distinguishes between `unsafe { ... }` and `{ ... }`.
     pub rules: BlockCheckMode,
     pub span: Span,
 }
@@ -561,29 +561,31 @@
         }))
     }
 
-    pub fn walk<F>(&self, it: &mut F) -> bool
-    where
-        F: FnMut(&Pat) -> bool,
-    {
+    /// Walk top-down and call `it` in each place where a pattern occurs
+    /// starting with the root pattern `walk` is called on. If `it` returns
+    /// false then we will descend no further but siblings will be processed.
+    pub fn walk(&self, it: &mut impl FnMut(&Pat) -> bool) {
         if !it(self) {
-            return false;
+            return;
         }
 
         match &self.node {
             PatKind::Ident(_, _, Some(p)) => p.walk(it),
-            PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk(it)),
+            PatKind::Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk(it)),
             PatKind::TupleStruct(_, s)
             | PatKind::Tuple(s)
             | PatKind::Slice(s)
-            | PatKind::Or(s) => s.iter().all(|p| p.walk(it)),
-            PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it),
+            | PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)),
+            PatKind::Box(s)
+            | PatKind::Ref(s, _)
+            | PatKind::Paren(s) => s.walk(it),
             PatKind::Wild
             | PatKind::Rest
             | PatKind::Lit(_)
             | PatKind::Range(..)
             | PatKind::Ident(..)
             | PatKind::Path(..)
-            | PatKind::Mac(_) => true,
+            | PatKind::Mac(_) => {},
         }
     }
 
@@ -611,6 +613,7 @@
     pub attrs: ThinVec<Attribute>,
     pub id: NodeId,
     pub span: Span,
+    pub is_placeholder: bool,
 }
 
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
@@ -906,11 +909,11 @@
 /// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Local {
+    pub id: NodeId,
     pub pat: P<Pat>,
     pub ty: Option<P<Ty>>,
     /// Initializer expression to set the value, if any.
     pub init: Option<P<Expr>>,
-    pub id: NodeId,
     pub span: Span,
     pub attrs: ThinVec<Attribute>,
 }
@@ -928,11 +931,12 @@
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Arm {
     pub attrs: Vec<Attribute>,
-    pub pats: Vec<P<Pat>>,
+    pub pat: P<Pat>,
     pub guard: Option<P<Expr>>,
     pub body: P<Expr>,
     pub span: Span,
     pub id: NodeId,
+    pub is_placeholder: bool,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -943,6 +947,7 @@
     pub is_shorthand: bool,
     pub attrs: ThinVec<Attribute>,
     pub id: NodeId,
+    pub is_placeholder: bool,
 }
 
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
@@ -968,7 +973,7 @@
     pub value: P<Expr>,
 }
 
-/// An expression
+/// An expression.
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub struct Expr {
     pub id: NodeId,
@@ -982,26 +987,26 @@
 static_assert_size!(Expr, 96);
 
 impl Expr {
-    /// Whether this expression would be valid somewhere that expects a value; for example, an `if`
-    /// condition.
+    /// Returns `true` if this expression would be valid somewhere that expects a value;
+    /// for example, an `if` condition.
     pub fn returns(&self) -> bool {
         if let ExprKind::Block(ref block, _) = self.node {
             match block.stmts.last().map(|last_stmt| &last_stmt.node) {
-                // implicit return
+                // Implicit return
                 Some(&StmtKind::Expr(_)) => true,
                 Some(&StmtKind::Semi(ref expr)) => {
                     if let ExprKind::Ret(_) = expr.node {
-                        // last statement is explicit return
+                        // Last statement is explicit return.
                         true
                     } else {
                         false
                     }
                 }
-                // This is a block that doesn't end in either an implicit or explicit return
+                // This is a block that doesn't end in either an implicit or explicit return.
                 _ => false,
             }
         } else {
-            // This is not a block, it is a value
+            // This is not a block, it is a value.
             true
         }
     }
@@ -1146,12 +1151,9 @@
     Cast(P<Expr>, P<Ty>),
     /// A type ascription (e.g., `42: usize`).
     Type(P<Expr>, P<Ty>),
-    /// A `let pats = expr` expression that is only semantically allowed in the condition
+    /// A `let pat = expr` expression that is only semantically allowed in the condition
     /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`).
-    ///
-    /// The `Vec<P<Pat>>` is for or-patterns at the top level.
-    /// FIXME(54883): Change this to just `P<Pat>`.
-    Let(Vec<P<Pat>>, P<Expr>),
+    Let(P<Pat>, P<Expr>),
     /// An `if` block, with an optional `else` block.
     ///
     /// `if expr { block } else { expr }`
@@ -1799,6 +1801,7 @@
     pub pat: P<Pat>,
     pub id: NodeId,
     pub span: Span,
+    pub is_placeholder: bool,
 }
 
 /// Alternative representation for `Arg`s describing `self` parameter of methods.
@@ -1860,6 +1863,7 @@
             span,
             ty,
             id: DUMMY_NODE_ID,
+            is_placeholder: false
         };
         match eself.node {
             SelfKind::Explicit(ty, mutbl) => param(mutbl, ty),
@@ -2055,6 +2059,8 @@
     pub disr_expr: Option<AnonConst>,
     /// Span
     pub span: Span,
+    /// Is a macro placeholder
+    pub is_placeholder: bool,
 }
 
 /// Part of `use` item to the right of its prefix.
@@ -2217,6 +2223,7 @@
     pub id: NodeId,
     pub ty: P<Ty>,
     pub attrs: Vec<Attribute>,
+    pub is_placeholder: bool,
 }
 
 /// Fields and constructor ids of enum variants and structs.
@@ -2308,37 +2315,37 @@
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum ItemKind {
-    /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
+    /// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
     ///
     /// E.g., `extern crate foo` or `extern crate foo_bar as foo`.
     ExternCrate(Option<Name>),
-    /// A use declaration (`use` or `pub use`) item.
+    /// A use declaration item (`use`).
     ///
     /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`.
     Use(P<UseTree>),
-    /// A static item (`static` or `pub static`).
+    /// A static item (`static`).
     ///
     /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`.
     Static(P<Ty>, Mutability, P<Expr>),
-    /// A constant item (`const` or `pub const`).
+    /// A constant item (`const`).
     ///
     /// E.g., `const FOO: i32 = 42;`.
     Const(P<Ty>, P<Expr>),
-    /// A function declaration (`fn` or `pub fn`).
+    /// A function declaration (`fn`).
     ///
     /// E.g., `fn foo(bar: usize) -> usize { .. }`.
     Fn(P<FnDecl>, FnHeader, Generics, P<Block>),
-    /// A module declaration (`mod` or `pub mod`).
+    /// A module declaration (`mod`).
     ///
     /// E.g., `mod foo;` or `mod foo { .. }`.
     Mod(Mod),
-    /// An external module (`extern` or `pub extern`).
+    /// An external module (`extern`).
     ///
     /// E.g., `extern {}` or `extern "C" {}`.
     ForeignMod(ForeignMod),
     /// Module-level inline assembly (from `global_asm!()`).
     GlobalAsm(P<GlobalAsm>),
-    /// A type alias (`type` or `pub type`).
+    /// A type alias (`type`).
     ///
     /// E.g., `type Foo = Bar<u8>;`.
     TyAlias(P<Ty>, Generics),
@@ -2346,19 +2353,19 @@
     ///
     /// E.g., `type Foo = impl Bar + Boo;`.
     OpaqueTy(GenericBounds, Generics),
-    /// An enum definition (`enum` or `pub enum`).
+    /// An enum definition (`enum`).
     ///
     /// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
     Enum(EnumDef, Generics),
-    /// A struct definition (`struct` or `pub struct`).
+    /// A struct definition (`struct`).
     ///
     /// E.g., `struct Foo<A> { x: A }`.
     Struct(VariantData, Generics),
-    /// A union definition (`union` or `pub union`).
+    /// A union definition (`union`).
     ///
     /// E.g., `union Foo<A, B> { x: A, y: B }`.
     Union(VariantData, Generics),
-    /// A Trait declaration (`trait` or `pub trait`).
+    /// A trait declaration (`trait`).
     ///
     /// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
     Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<TraitItem>),
@@ -2380,7 +2387,7 @@
     ),
     /// A macro invocation.
     ///
-    /// E.g., `macro_rules! foo { .. }` or `foo!(..)`.
+    /// E.g., `foo!(..)`.
     Mac(Mac),
 
     /// A macro definition.
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index 5fb5137..b5037b7 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -154,23 +154,10 @@
 #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
 pub enum StabilityLevel {
     // Reason for the current stability level and the relevant rust-lang issue
-    Unstable { reason: Option<Symbol>, issue: u32 },
+    Unstable { reason: Option<Symbol>, issue: u32, is_soft: bool },
     Stable { since: Symbol },
 }
 
-impl Stability {
-    pub fn unstable(feature: Symbol, reason: Option<Symbol>, issue: u32) -> Stability {
-        Stability {
-            level: StabilityLevel::Unstable { reason, issue },
-            feature,
-            rustc_depr: None,
-            const_stability: None,
-            promotable: false,
-            allow_const_fn_ptr: false,
-        }
-    }
-}
-
 impl StabilityLevel {
     pub fn is_unstable(&self) -> bool {
         if let StabilityLevel::Unstable {..} = *self {
@@ -356,19 +343,27 @@
                     let mut feature = None;
                     let mut reason = None;
                     let mut issue = None;
+                    let mut is_soft = false;
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
                             match mi.name_or_empty() {
                                 sym::feature => if !get(mi, &mut feature) { continue 'outer },
                                 sym::reason => if !get(mi, &mut reason) { continue 'outer },
                                 sym::issue => if !get(mi, &mut issue) { continue 'outer },
+                                sym::soft => {
+                                    if !mi.is_word() {
+                                        let msg = "`soft` should not have any arguments";
+                                        sess.span_diagnostic.span_err(mi.span, msg);
+                                    }
+                                    is_soft = true;
+                                }
                                 _ => {
                                     handle_errors(
                                         sess,
                                         meta.span(),
                                         AttrError::UnknownMetaItem(
                                             mi.path.to_string(),
-                                            &["feature", "reason", "issue"]
+                                            &["feature", "reason", "issue", "soft"]
                                         ),
                                     );
                                     continue 'outer
@@ -400,7 +395,8 @@
                                                       "incorrect 'issue'");
                                             continue
                                         }
-                                    }
+                                    },
+                                    is_soft,
                                 },
                                 feature,
                                 rustc_depr: None,
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 0e5cfa7..1f95406 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -1,4 +1,4 @@
-//! Functions dealing with attributes and meta items
+//! Functions dealing with attributes and meta items.
 
 mod builtin;
 
@@ -16,7 +16,7 @@
 use crate::source_map::{BytePos, Spanned, DUMMY_SP};
 use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
 use crate::parse::parser::Parser;
-use crate::parse::{self, ParseSess, PResult};
+use crate::parse::{ParseSess, PResult};
 use crate::parse::token::{self, Token};
 use crate::ptr::P;
 use crate::symbol::{sym, Symbol};
@@ -25,7 +25,7 @@
 use crate::GLOBALS;
 
 use log::debug;
-use syntax_pos::{FileName, Span};
+use syntax_pos::Span;
 
 use std::iter;
 use std::ops::DerefMut;
@@ -61,7 +61,7 @@
 }
 
 impl NestedMetaItem {
-    /// Returns the MetaItem if self is a NestedMetaItem::MetaItem.
+    /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
     pub fn meta_item(&self) -> Option<&MetaItem> {
         match *self {
             NestedMetaItem::MetaItem(ref item) => Some(item),
@@ -69,7 +69,7 @@
         }
     }
 
-    /// Returns the Lit if self is a NestedMetaItem::Literal.
+    /// Returns the `Lit` if `self` is a `NestedMetaItem::Literal`s.
     pub fn literal(&self) -> Option<&Lit> {
         match *self {
             NestedMetaItem::Literal(ref lit) => Some(lit),
@@ -82,7 +82,7 @@
         self.meta_item().map_or(false, |meta_item| meta_item.check_name(name))
     }
 
-    /// For a single-segment meta-item returns its name, otherwise returns `None`.
+    /// For a single-segment meta item, returns its name; otherwise, returns `None`.
     pub fn ident(&self) -> Option<Ident> {
         self.meta_item().and_then(|meta_item| meta_item.ident())
     }
@@ -90,13 +90,13 @@
         self.ident().unwrap_or(Ident::invalid()).name
     }
 
-    /// Gets the string value if self is a MetaItem and the MetaItem is a
-    /// MetaItemKind::NameValue variant containing a string, otherwise None.
+    /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
+    /// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
     pub fn value_str(&self) -> Option<Symbol> {
         self.meta_item().and_then(|meta_item| meta_item.value_str())
     }
 
-    /// Returns a name and single literal value tuple of the MetaItem.
+    /// Returns a name and single literal value tuple of the `MetaItem`.
     pub fn name_value_literal(&self) -> Option<(Name, &Lit)> {
         self.meta_item().and_then(
             |meta_item| meta_item.meta_item_list().and_then(
@@ -112,32 +112,32 @@
                 }))
     }
 
-    /// Gets a list of inner meta items from a list MetaItem type.
+    /// Gets a list of inner meta items from a list `MetaItem` type.
     pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
         self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
     }
 
-    /// Returns `true` if the variant is MetaItem.
+    /// Returns `true` if the variant is `MetaItem`.
     pub fn is_meta_item(&self) -> bool {
         self.meta_item().is_some()
     }
 
-    /// Returns `true` if the variant is Literal.
+    /// Returns `true` if the variant is `Literal`.
     pub fn is_literal(&self) -> bool {
         self.literal().is_some()
     }
 
-    /// Returns `true` if self is a MetaItem and the meta item is a word.
+    /// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
     pub fn is_word(&self) -> bool {
         self.meta_item().map_or(false, |meta_item| meta_item.is_word())
     }
 
-    /// Returns `true` if self is a MetaItem and the meta item is a ValueString.
+    /// Returns `true` if `self` is a `MetaItem` and the meta item is a `ValueString`.
     pub fn is_value_str(&self) -> bool {
         self.value_str().is_some()
     }
 
-    /// Returns `true` if self is a MetaItem and the meta item is a list.
+    /// Returns `true` if `self` is a `MetaItem` and the meta item is a list.
     pub fn is_meta_item_list(&self) -> bool {
         self.meta_item_list().is_some()
     }
@@ -156,7 +156,7 @@
         matches
     }
 
-    /// For a single-segment attribute returns its name, otherwise returns `None`.
+    /// For a single-segment attribute, returns its name; otherwise, returns `None`.
     pub fn ident(&self) -> Option<Ident> {
         if self.path.segments.len() == 1 {
             Some(self.path.segments[0].ident)
@@ -187,14 +187,14 @@
         self.meta_item_list().is_some()
     }
 
-    /// Indicates if the attribute is a Value String.
+    /// Indicates if the attribute is a `ValueString`.
     pub fn is_value_str(&self) -> bool {
         self.value_str().is_some()
     }
 }
 
 impl MetaItem {
-    /// For a single-segment meta-item returns its name, otherwise returns `None`.
+    /// For a single-segment meta item, returns its name; otherwise, returns `None`.
     pub fn ident(&self) -> Option<Ident> {
         if self.path.segments.len() == 1 {
             Some(self.path.segments[0].ident)
@@ -206,8 +206,9 @@
         self.ident().unwrap_or(Ident::invalid()).name
     }
 
-    // #[attribute(name = "value")]
-    //             ^^^^^^^^^^^^^^
+    // Example:
+    //     #[attribute(name = "value")]
+    //                 ^^^^^^^^^^^^^^
     pub fn name_value_literal(&self) -> Option<&Lit> {
         match &self.node {
             MetaItemKind::NameValue(v) => Some(v),
@@ -255,7 +256,7 @@
 }
 
 impl Attribute {
-    /// Extracts the MetaItem from inside this Attribute.
+    /// Extracts the `MetaItem` from inside this `Attribute`.
     pub fn meta(&self) -> Option<MetaItem> {
         let mut tokens = self.tokens.trees().peekable();
         Some(MetaItem {
@@ -318,8 +319,8 @@
         })
     }
 
-    /// Converts self to a normal #[doc="foo"] comment, if it is a
-    /// comment like `///` or `/** */`. (Returns self unchanged for
+    /// Converts `self` to a normal `#[doc="foo"]` comment, if it is a
+    /// comment like `///` or `/** */`. (Returns `self` unchanged for
     /// non-sugared doc attributes.)
     pub fn with_desugared_doc<T, F>(&self, f: F) -> T where
         F: FnOnce(&Attribute) -> T,
@@ -381,28 +382,25 @@
     AttrId(id)
 }
 
-/// Returns an inner attribute with the given value and span.
-pub fn mk_attr_inner(item: MetaItem) -> Attribute {
+pub fn mk_attr(style: AttrStyle, path: Path, tokens: TokenStream, span: Span) -> Attribute {
     Attribute {
         id: mk_attr_id(),
-        style: ast::AttrStyle::Inner,
-        path: item.path,
-        tokens: item.node.tokens(item.span),
+        style,
+        path,
+        tokens,
         is_sugared_doc: false,
-        span: item.span,
+        span,
     }
 }
 
+/// Returns an inner attribute with the given value and span.
+pub fn mk_attr_inner(item: MetaItem) -> Attribute {
+    mk_attr(AttrStyle::Inner, item.path, item.node.tokens(item.span), item.span)
+}
+
 /// Returns an outer attribute with the given value and span.
 pub fn mk_attr_outer(item: MetaItem) -> Attribute {
-    Attribute {
-        id: mk_attr_id(),
-        style: ast::AttrStyle::Outer,
-        path: item.path,
-        tokens: item.node.tokens(item.span),
-        is_sugared_doc: false,
-        span: item.span,
-    }
+    mk_attr(AttrStyle::Outer, item.path, item.node.tokens(item.span), item.span)
 }
 
 pub fn mk_sugared_doc_attr(text: Symbol, span: Span) -> Attribute {
@@ -716,33 +714,3 @@
     Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
     ast::Field, ast::FieldPat, ast::Variant, ast::Param
 }
-
-pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate {
-    for raw_attr in attrs {
-        let mut parser = parse::new_parser_from_source_str(
-            parse_sess,
-            FileName::cli_crate_attr_source_code(&raw_attr),
-            raw_attr.clone(),
-        );
-
-        let start_span = parser.token.span;
-        let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted());
-        let end_span = parser.token.span;
-        if parser.token != token::Eof {
-            parse_sess.span_diagnostic
-                .span_err(start_span.to(end_span), "invalid crate attribute");
-            continue;
-        }
-
-        krate.attrs.push(Attribute {
-            id: mk_attr_id(),
-            style: AttrStyle::Inner,
-            path,
-            tokens,
-            is_sugared_doc: false,
-            span: start_span.to(end_span),
-        });
-    }
-
-    krate
-}
diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs
index b754d08..c95c5bd 100644
--- a/src/libsyntax/diagnostics/macros.rs
+++ b/src/libsyntax/diagnostics/macros.rs
@@ -1,13 +1,14 @@
 #[macro_export]
-macro_rules! register_diagnostic {
-    ($code:tt, $description:tt) => (__register_diagnostic! { $code, $description });
-    ($code:tt) => (__register_diagnostic! { $code })
+macro_rules! diagnostic_used {
+    ($code:ident) => (
+        let _ = crate::error_codes::$code;
+    )
 }
 
 #[macro_export]
 macro_rules! span_fatal {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         $session.span_fatal_with_code(
             $span,
             &format!($($message)*),
@@ -19,7 +20,7 @@
 #[macro_export]
 macro_rules! span_err {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         $session.span_err_with_code(
             $span,
             &format!($($message)*),
@@ -31,7 +32,7 @@
 #[macro_export]
 macro_rules! span_warn {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         $session.span_warn_with_code(
             $span,
             &format!($($message)*),
@@ -43,7 +44,7 @@
 #[macro_export]
 macro_rules! struct_err {
     ($session:expr, $code:ident, $($message:tt)*) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         $session.struct_err_with_code(
             &format!($($message)*),
             $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
@@ -54,7 +55,7 @@
 #[macro_export]
 macro_rules! span_err_or_warn {
     ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         if $is_warning {
             $session.span_warn_with_code(
                 $span,
@@ -74,7 +75,7 @@
 #[macro_export]
 macro_rules! struct_span_fatal {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         $session.struct_span_fatal_with_code(
             $span,
             &format!($($message)*),
@@ -86,7 +87,7 @@
 #[macro_export]
 macro_rules! struct_span_err {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         $session.struct_span_err_with_code(
             $span,
             &format!($($message)*),
@@ -98,7 +99,7 @@
 #[macro_export]
 macro_rules! stringify_error_code {
     ($code:ident) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         $crate::errors::DiagnosticId::Error(stringify!($code).to_owned())
     })
 }
@@ -117,7 +118,7 @@
 #[macro_export]
 macro_rules! struct_span_warn {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         $session.struct_span_warn_with_code(
             $span,
             &format!($($message)*),
@@ -129,7 +130,7 @@
 #[macro_export]
 macro_rules! struct_span_err_or_warn {
     ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        __diagnostic_used!($code);
+        $crate::diagnostic_used!($code);
         if $is_warning {
             $session.struct_span_warn_with_code(
                 $span,
@@ -169,20 +170,22 @@
 
 #[macro_export]
 macro_rules! register_diagnostics {
-    ($($code:tt),*) => (
-        $($crate::register_diagnostic! { $code })*
+    ($($ecode:ident: $message:expr,)*) => (
+        $crate::register_diagnostics!{$($ecode:$message,)* ;}
     );
-    ($($code:tt),*,) => (
-        $($crate::register_diagnostic! { $code })*
-    )
-}
 
-#[macro_export]
-macro_rules! register_long_diagnostics {
-    ($($code:tt: $description:tt),*) => (
-        $($crate::register_diagnostic! { $code, $description })*
-    );
-    ($($code:tt: $description:tt),*,) => (
-        $($crate::register_diagnostic! { $code, $description })*
+    ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
+        pub static DIAGNOSTICS: &[(&str, &str)] = &[
+            $( (stringify!($ecode), $message), )*
+        ];
+
+        $(
+            #[deny(unused)]
+            pub(crate) const $ecode: &str = $message;
+        )*
+        $(
+            #[deny(unused)]
+            pub(crate) const $code: () = ();
+        )*
     )
 }
diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs
deleted file mode 100644
index e9a55af..0000000
--- a/src/libsyntax/diagnostics/plugin.rs
+++ /dev/null
@@ -1,185 +0,0 @@
-use std::collections::BTreeMap;
-
-use crate::ast::{self, Ident, Name};
-use crate::source_map;
-use crate::ext::base::{ExtCtxt, MacEager, MacResult};
-use crate::parse::token::{self, Token};
-use crate::ptr::P;
-use crate::symbol::kw;
-use crate::tokenstream::{TokenTree};
-
-use smallvec::smallvec;
-use syntax_pos::Span;
-
-pub use errors::*;
-
-// Maximum width of any line in an extended error description (inclusive).
-const MAX_DESCRIPTION_WIDTH: usize = 80;
-
-/// Error information type.
-pub struct ErrorInfo {
-    pub description: Option<Name>,
-    pub use_site: Option<Span>
-}
-
-/// Mapping from error codes to metadata.
-pub type ErrorMap = BTreeMap<Name, ErrorInfo>;
-
-pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt<'_>,
-                                   span: Span,
-                                   token_tree: &[TokenTree])
-                                   -> Box<dyn MacResult+'cx> {
-    let code = match token_tree {
-        [
-            TokenTree::Token(Token { kind: token::Ident(code, _), .. })
-        ] => code,
-        _ => unreachable!()
-    };
-
-    ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| {
-        match diagnostics.get_mut(&code) {
-            // Previously used errors.
-            Some(&mut ErrorInfo { description: _, use_site: Some(previous_span) }) => {
-                ecx.struct_span_warn(span, &format!(
-                    "diagnostic code {} already used", code
-                )).span_note(previous_span, "previous invocation")
-                  .emit();
-            }
-            // Newly used errors.
-            Some(ref mut info) => {
-                info.use_site = Some(span);
-            }
-            // Unregistered errors.
-            None => {
-                ecx.span_err(span, &format!(
-                    "used diagnostic code {} not registered", code
-                ));
-            }
-        }
-    });
-    MacEager::expr(ecx.expr_tuple(span, Vec::new()))
-}
-
-pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt<'_>,
-                                       span: Span,
-                                       token_tree: &[TokenTree])
-                                       -> Box<dyn MacResult+'cx> {
-    let (code, description) = match  token_tree {
-        [
-            TokenTree::Token(Token { kind: token::Ident(code, _), .. })
-        ] => {
-            (*code, None)
-        },
-        [
-            TokenTree::Token(Token { kind: token::Ident(code, _), .. }),
-            TokenTree::Token(Token { kind: token::Comma, .. }),
-            TokenTree::Token(Token { kind: token::Literal(token::Lit { symbol, .. }), ..})
-        ] => {
-            (*code, Some(*symbol))
-        },
-        _ => unreachable!()
-    };
-
-    // Check that the description starts and ends with a newline and doesn't
-    // overflow the maximum line width.
-    description.map(|raw_msg| {
-        let msg = raw_msg.as_str();
-        if !msg.starts_with("\n") || !msg.ends_with("\n") {
-            ecx.span_err(span, &format!(
-                "description for error code {} doesn't start and end with a newline",
-                code
-            ));
-        }
-
-        // URLs can be unavoidably longer than the line limit, so we allow them.
-        // Allowed format is: `[name]: https://www.rust-lang.org/`
-        let is_url = |l: &str| l.starts_with("[") && l.contains("]:") && l.contains("http");
-
-        if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH && !is_url(line)) {
-            ecx.span_err(span, &format!(
-                "description for error code {} contains a line longer than {} characters.\n\
-                 if you're inserting a long URL use the footnote style to bypass this check.",
-                code, MAX_DESCRIPTION_WIDTH
-            ));
-        }
-    });
-    // Add the error to the map.
-    ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| {
-        let info = ErrorInfo {
-            description,
-            use_site: None
-        };
-        if diagnostics.insert(code, info).is_some() {
-            ecx.span_err(span, &format!(
-                "diagnostic code {} already registered", code
-            ));
-        }
-    });
-
-    MacEager::items(smallvec![])
-}
-
-pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>,
-                                          span: Span,
-                                          token_tree: &[TokenTree])
-                                          -> Box<dyn MacResult+'cx> {
-    assert_eq!(token_tree.len(), 3);
-    let ident = match &token_tree[2] {
-        // DIAGNOSTICS ident.
-        &TokenTree::Token(Token { kind: token::Ident(name, _), span })
-        => Ident::new(name, span),
-        _ => unreachable!()
-    };
-
-    // Construct the output expression.
-    let (count, expr) =
-        ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| {
-            let descriptions: Vec<P<ast::Expr>> =
-                diagnostics.iter().filter_map(|(&code, info)| {
-                    info.description.map(|description| {
-                        ecx.expr_tuple(span, vec![
-                            ecx.expr_str(span, code),
-                            ecx.expr_str(span, description)
-                        ])
-                    })
-                }).collect();
-            (descriptions.len(), ecx.expr_vec(span, descriptions))
-        });
-
-    let static_ = ecx.lifetime(span, Ident::with_dummy_span(kw::StaticLifetime));
-    let ty_str = ecx.ty_rptr(
-        span,
-        ecx.ty_ident(span, ecx.ident_of("str")),
-        Some(static_),
-        ast::Mutability::Immutable,
-    );
-
-    let ty = ecx.ty(
-        span,
-        ast::TyKind::Array(
-            ecx.ty(
-                span,
-                ast::TyKind::Tup(vec![ty_str.clone(), ty_str])
-            ),
-            ast::AnonConst {
-                id: ast::DUMMY_NODE_ID,
-                value: ecx.expr_usize(span, count),
-            },
-        ),
-    );
-
-    MacEager::items(smallvec![
-        P(ast::Item {
-            ident,
-            attrs: Vec::new(),
-            id: ast::DUMMY_NODE_ID,
-            node: ast::ItemKind::Const(
-                ty,
-                expr,
-            ),
-            vis: source_map::respan(span.shrink_to_lo(), ast::VisibilityKind::Public),
-            span,
-            tokens: None,
-        })
-    ])
-}
diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs
index 1ba2901..9925dd8 100644
--- a/src/libsyntax/error_codes.rs
+++ b/src/libsyntax/error_codes.rs
@@ -1,7 +1,8 @@
 // Error messages for EXXXX errors.
-// Each message should start and end with a new line, and be wrapped to 80 characters.
-// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
-register_long_diagnostics! {
+// Each message should start and end with a new line, and be wrapped to 80
+// characters.  In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use
+// `:set tw=0` to disable.
+register_diagnostics! {
 
 E0178: r##"
 In types, the `+` type operator has low precedence, so it is often necessary
@@ -420,9 +421,8 @@
 features in the `-Z allow_features` flag.
 "##,
 
-}
+;
 
-register_diagnostics! {
     E0539, // incorrect meta item
     E0540, // multiple rustc_deprecated attributes
     E0542, // missing 'since'
@@ -432,7 +432,9 @@
     E0546, // missing 'feature'
     E0547, // missing 'issue'
 //  E0548, // replaced with a generic attribute input check
-    E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
+    // rustc_deprecated attribute must be paired with either stable or unstable
+    // attribute
+    E0549,
     E0550, // multiple deprecated attributes
     E0551, // incorrect meta item
     E0553, // multiple rustc_const_unstable attributes
@@ -440,9 +442,11 @@
     E0556, // malformed feature, expected just one word
     E0584, // file for module `..` found at both .. and ..
     E0629, // missing 'feature' (rustc_const_unstable)
-    E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute
+    // rustc_const_unstable attribute must be paired with stable/unstable
+    // attribute
+    E0630,
     E0693, // incorrect `repr(align)` attribute format
-    E0694, // an unknown tool name found in scoped attributes
+//  E0694, // an unknown tool name found in scoped attributes
     E0703, // invalid ABI
     E0717, // rustc_promotable without stability attribute
 }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 5d68983..384c055 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -3,20 +3,20 @@
 use crate::source_map::SourceMap;
 use crate::edition::Edition;
 use crate::ext::expand::{self, AstFragment, Invocation};
-use crate::ext::hygiene::{ExpnId, Transparency};
+use crate::ext::hygiene::ExpnId;
 use crate::mut_visit::{self, MutVisitor};
 use crate::parse::{self, parser, ParseSess, DirectoryOwnership};
 use crate::parse::token;
 use crate::ptr::P;
 use crate::symbol::{kw, sym, Ident, Symbol};
 use crate::{ThinVec, MACRO_ARGUMENTS};
-use crate::tokenstream::{self, TokenStream, TokenTree};
+use crate::tokenstream::{self, TokenStream};
 use crate::visit::Visitor;
 
 use errors::{DiagnosticBuilder, DiagnosticId};
 use smallvec::{smallvec, SmallVec};
 use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP};
-use syntax_pos::hygiene::{ExpnData, ExpnKind};
+use syntax_pos::hygiene::{AstPass, ExpnData, ExpnKind};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
@@ -35,6 +35,13 @@
     ForeignItem(P<ast::ForeignItem>),
     Stmt(P<ast::Stmt>),
     Expr(P<ast::Expr>),
+    Arm(ast::Arm),
+    Field(ast::Field),
+    FieldPat(ast::FieldPat),
+    GenericParam(ast::GenericParam),
+    Param(ast::Param),
+    StructField(ast::StructField),
+    Variant(ast::Variant),
 }
 
 impl HasAttrs for Annotatable {
@@ -46,6 +53,13 @@
             Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs,
             Annotatable::Stmt(ref stmt) => stmt.attrs(),
             Annotatable::Expr(ref expr) => &expr.attrs,
+            Annotatable::Arm(ref arm) => &arm.attrs,
+            Annotatable::Field(ref field) => &field.attrs,
+            Annotatable::FieldPat(ref fp) => &fp.attrs,
+            Annotatable::GenericParam(ref gp) => &gp.attrs,
+            Annotatable::Param(ref p) => &p.attrs,
+            Annotatable::StructField(ref sf) => &sf.attrs,
+            Annotatable::Variant(ref v) => &v.attrs(),
         }
     }
 
@@ -57,6 +71,13 @@
             Annotatable::ForeignItem(foreign_item) => foreign_item.visit_attrs(f),
             Annotatable::Stmt(stmt) => stmt.visit_attrs(f),
             Annotatable::Expr(expr) => expr.visit_attrs(f),
+            Annotatable::Arm(arm) => arm.visit_attrs(f),
+            Annotatable::Field(field) => field.visit_attrs(f),
+            Annotatable::FieldPat(fp) => fp.visit_attrs(f),
+            Annotatable::GenericParam(gp) => gp.visit_attrs(f),
+            Annotatable::Param(p) => p.visit_attrs(f),
+            Annotatable::StructField(sf) => sf.visit_attrs(f),
+            Annotatable::Variant(v) => v.visit_attrs(f),
         }
     }
 }
@@ -70,6 +91,13 @@
             Annotatable::ForeignItem(ref foreign_item) => foreign_item.span,
             Annotatable::Stmt(ref stmt) => stmt.span,
             Annotatable::Expr(ref expr) => expr.span,
+            Annotatable::Arm(ref arm) => arm.span,
+            Annotatable::Field(ref field) => field.span,
+            Annotatable::FieldPat(ref fp) => fp.pat.span,
+            Annotatable::GenericParam(ref gp) => gp.ident.span,
+            Annotatable::Param(ref p) => p.span,
+            Annotatable::StructField(ref sf) => sf.span,
+            Annotatable::Variant(ref v) => v.span,
         }
     }
 
@@ -81,6 +109,13 @@
             Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item),
             Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt),
             Annotatable::Expr(expr) => visitor.visit_expr(expr),
+            Annotatable::Arm(arm) => visitor.visit_arm(arm),
+            Annotatable::Field(field) => visitor.visit_field(field),
+            Annotatable::FieldPat(fp) => visitor.visit_field_pattern(fp),
+            Annotatable::GenericParam(gp) => visitor.visit_generic_param(gp),
+            Annotatable::Param(p) => visitor.visit_param(p),
+            Annotatable::StructField(sf) =>visitor.visit_struct_field(sf),
+            Annotatable::Variant(v) => visitor.visit_variant(v),
         }
     }
 
@@ -136,6 +171,55 @@
         }
     }
 
+    pub fn expect_arm(self) -> ast::Arm {
+        match self {
+            Annotatable::Arm(arm) => arm,
+            _ => panic!("expected match arm")
+        }
+    }
+
+    pub fn expect_field(self) -> ast::Field {
+        match self {
+            Annotatable::Field(field) => field,
+            _ => panic!("expected field")
+        }
+    }
+
+    pub fn expect_field_pattern(self) -> ast::FieldPat {
+        match self {
+            Annotatable::FieldPat(fp) => fp,
+            _ => panic!("expected field pattern")
+        }
+    }
+
+    pub fn expect_generic_param(self) -> ast::GenericParam {
+        match self {
+            Annotatable::GenericParam(gp) => gp,
+            _ => panic!("expected generic parameter")
+        }
+    }
+
+    pub fn expect_param(self) -> ast::Param {
+        match self {
+            Annotatable::Param(param) => param,
+            _ => panic!("expected parameter")
+        }
+    }
+
+    pub fn expect_struct_field(self) -> ast::StructField {
+        match self {
+            Annotatable::StructField(sf) => sf,
+            _ => panic!("expected struct field")
+        }
+    }
+
+    pub fn expect_variant(self) -> ast::Variant {
+        match self {
+            Annotatable::Variant(v) => v,
+            _ => panic!("expected variant")
+        }
+    }
+
     pub fn derive_allowed(&self) -> bool {
         match *self {
             Annotatable::Item(ref item) => match item.node {
@@ -235,18 +319,18 @@
 }
 
 pub type MacroExpanderFn =
-    for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, &[tokenstream::TokenTree])
+    for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream)
                 -> Box<dyn MacResult+'cx>;
 
 impl<F> TTMacroExpander for F
-    where F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, &[tokenstream::TokenTree])
+    where F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream)
     -> Box<dyn MacResult+'cx>
 {
     fn expand<'cx>(
         &self,
         ecx: &'cx mut ExtCtxt<'_>,
         span: Span,
-        input: TokenStream,
+        mut input: TokenStream,
     ) -> Box<dyn MacResult+'cx> {
         struct AvoidInterpolatedIdents;
 
@@ -268,10 +352,8 @@
                 mut_visit::noop_visit_mac(mac, self)
             }
         }
-
-        let input: Vec<_> =
-            input.trees().map(|mut tt| { AvoidInterpolatedIdents.visit_tt(&mut tt); tt }).collect();
-        (*self)(ecx, span, &input)
+        AvoidInterpolatedIdents.visit_tts(&mut input);
+        (*self)(ecx, span, input)
     }
 }
 
@@ -327,6 +409,34 @@
     fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
         None
     }
+
+    fn make_arms(self: Box<Self>) -> Option<SmallVec<[ast::Arm; 1]>> {
+        None
+    }
+
+    fn make_fields(self: Box<Self>) -> Option<SmallVec<[ast::Field; 1]>> {
+        None
+    }
+
+    fn make_field_patterns(self: Box<Self>) -> Option<SmallVec<[ast::FieldPat; 1]>> {
+        None
+    }
+
+    fn make_generic_params(self: Box<Self>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
+        None
+    }
+
+    fn make_params(self: Box<Self>) -> Option<SmallVec<[ast::Param; 1]>> {
+        None
+    }
+
+    fn make_struct_fields(self: Box<Self>) -> Option<SmallVec<[ast::StructField; 1]>> {
+        None
+    }
+
+    fn make_variants(self: Box<Self>) -> Option<SmallVec<[ast::Variant; 1]>> {
+        None
+    }
 }
 
 macro_rules! make_MacEager {
@@ -500,6 +610,34 @@
     fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
         Some(DummyResult::raw_ty(self.span, self.is_error))
     }
+
+    fn make_arms(self: Box<DummyResult>) -> Option<SmallVec<[ast::Arm; 1]>> {
+       Some(SmallVec::new())
+    }
+
+    fn make_fields(self: Box<DummyResult>) -> Option<SmallVec<[ast::Field; 1]>> {
+        Some(SmallVec::new())
+    }
+
+    fn make_field_patterns(self: Box<DummyResult>) -> Option<SmallVec<[ast::FieldPat; 1]>> {
+        Some(SmallVec::new())
+    }
+
+    fn make_generic_params(self: Box<DummyResult>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
+        Some(SmallVec::new())
+    }
+
+    fn make_params(self: Box<DummyResult>) -> Option<SmallVec<[ast::Param; 1]>> {
+        Some(SmallVec::new())
+    }
+
+    fn make_struct_fields(self: Box<DummyResult>) -> Option<SmallVec<[ast::StructField; 1]>> {
+        Some(SmallVec::new())
+    }
+
+    fn make_variants(self: Box<DummyResult>) -> Option<SmallVec<[ast::Variant; 1]>> {
+        Some(SmallVec::new())
+    }
 }
 
 /// A syntax extension kind.
@@ -677,7 +815,7 @@
     }
 
     pub fn dummy_bang(edition: Edition) -> SyntaxExtension {
-        fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree])
+        fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: TokenStream)
                          -> Box<dyn MacResult + 'cx> {
             DummyResult::any(span)
         }
@@ -734,13 +872,19 @@
 pub trait Resolver {
     fn next_node_id(&mut self) -> NodeId;
 
-    fn get_module_scope(&mut self, id: NodeId) -> ExpnId;
-
     fn resolve_dollar_crates(&mut self);
     fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment,
                                             extra_placeholders: &[NodeId]);
     fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension);
 
+    fn expansion_for_ast_pass(
+        &mut self,
+        call_site: Span,
+        pass: AstPass,
+        features: &[Symbol],
+        parent_module_id: Option<NodeId>,
+    ) -> ExpnId;
+
     fn resolve_imports(&mut self);
 
     fn resolve_macro_invocation(
@@ -811,9 +955,8 @@
     pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
         expand::MacroExpander::new(self, true)
     }
-
-    pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> {
-        parse::stream_to_parser(self.parse_sess, tts.iter().cloned().collect(), MACRO_ARGUMENTS)
+    pub fn new_parser_from_tts(&self, stream: TokenStream) -> parser::Parser<'a> {
+        parse::stream_to_parser(self.parse_sess, stream, MACRO_ARGUMENTS)
     }
     pub fn source_map(&self) -> &'a SourceMap { self.parse_sess.source_map() }
     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
@@ -825,20 +968,13 @@
     /// Equivalent of `Span::def_site` from the proc macro API,
     /// except that the location is taken from the span passed as an argument.
     pub fn with_def_site_ctxt(&self, span: Span) -> Span {
-        span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Opaque)
+        span.with_def_site_ctxt(self.current_expansion.id)
     }
 
     /// Equivalent of `Span::call_site` from the proc macro API,
     /// except that the location is taken from the span passed as an argument.
     pub fn with_call_site_ctxt(&self, span: Span) -> Span {
-        span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Transparent)
-    }
-
-    /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
-    /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
-    /// or with `with_call_site_ctxt` (where necessary).
-    pub fn with_legacy_ctxt(&self, span: Span) -> Span {
-        span.with_ctxt_from_mark(self.current_expansion.id, Transparency::SemiTransparent)
+        span.with_call_site_ctxt(self.current_expansion.id)
     }
 
     /// Returns span for the macro which originally caused the current expansion to happen.
@@ -938,8 +1074,8 @@
     pub fn set_trace_macros(&mut self, x: bool) {
         self.ecfg.trace_mac = x
     }
-    pub fn ident_of(&self, st: &str) -> ast::Ident {
-        ast::Ident::from_str(st)
+    pub fn ident_of(&self, st: &str, sp: Span) -> ast::Ident {
+        ast::Ident::from_str_and_span(st, sp)
     }
     pub fn std_path(&self, components: &[Symbol]) -> Vec<ast::Ident> {
         let def_site = self.with_def_site_ctxt(DUMMY_SP);
@@ -955,7 +1091,7 @@
         self.resolver.check_unused_macros();
     }
 
-    /// Resolve a path mentioned inside Rust code.
+    /// Resolves a path mentioned inside Rust code.
     ///
     /// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
     ///
@@ -1019,7 +1155,7 @@
 /// done as rarely as possible).
 pub fn check_zero_tts(cx: &ExtCtxt<'_>,
                       sp: Span,
-                      tts: &[tokenstream::TokenTree],
+                      tts: TokenStream,
                       name: &str) {
     if !tts.is_empty() {
         cx.span_err(sp, &format!("{} takes no arguments", name));
@@ -1030,7 +1166,7 @@
 /// expect exactly one string literal, or emit an error and return `None`.
 pub fn get_single_str_from_tts(cx: &mut ExtCtxt<'_>,
                                sp: Span,
-                               tts: &[tokenstream::TokenTree],
+                               tts: TokenStream,
                                name: &str)
                                -> Option<String> {
     let mut p = cx.new_parser_from_tts(tts);
@@ -1053,7 +1189,7 @@
 /// parsing error, emit a non-fatal error and return `None`.
 pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>,
                           sp: Span,
-                          tts: &[tokenstream::TokenTree]) -> Option<Vec<P<ast::Expr>>> {
+                          tts: TokenStream) -> Option<Vec<P<ast::Expr>>> {
     let mut p = cx.new_parser_from_tts(tts);
     let mut es = Vec::new();
     while p.token != token::Eof {
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index e894fd1..f1d0e0b 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -166,7 +166,8 @@
             bounds,
             kind: ast::GenericParamKind::Type {
                 default,
-            }
+            },
+            is_placeholder: false
         }
     }
 
@@ -207,6 +208,7 @@
             attrs: attrs.into(),
             bounds,
             kind: ast::GenericParamKind::Lifetime,
+            is_placeholder: false
         }
     }
 
@@ -361,7 +363,7 @@
         self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp)))
     }
     pub fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> {
-        let ident = Ident::from_str(&idx.to_string()).with_span_pos(sp);
+        let ident = Ident::new(sym::integer(idx), sp);
         self.expr(sp, ast::ExprKind::Field(expr, ident))
     }
     pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
@@ -404,6 +406,7 @@
             is_shorthand: false,
             attrs: ThinVec::new(),
             id: ast::DUMMY_NODE_ID,
+            is_placeholder: false,
         }
     }
     pub fn expr_struct(
@@ -522,7 +525,7 @@
         let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
         let err_path = self.path_global(sp, err);
 
-        let binding_variable = self.ident_of("__try_var");
+        let binding_variable = self.ident_of("__try_var", sp);
         let binding_pat = self.pat_ident(sp, binding_variable);
         let binding_expr = self.expr_ident(sp, binding_variable);
 
@@ -537,9 +540,9 @@
         let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr)));
 
         // `Ok(__try_var) => __try_var`
-        let ok_arm = self.arm(sp, vec![ok_pat], binding_expr);
+        let ok_arm = self.arm(sp, ok_pat, binding_expr);
         // `Err(__try_var) => return Err(__try_var)`
-        let err_arm = self.arm(sp, vec![err_pat], err_expr);
+        let err_arm = self.arm(sp, err_pat, err_expr);
 
         // `match head { Ok() => ..., Err() => ... }`
         self.expr_match(sp, head, vec![ok_arm, err_arm])
@@ -606,19 +609,20 @@
         self.pat_tuple_struct(span, path, vec![pat])
     }
 
-    pub fn arm(&self, span: Span, pats: Vec<P<ast::Pat>>, expr: P<ast::Expr>) -> ast::Arm {
+    pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
         ast::Arm {
             attrs: vec![],
-            pats,
+            pat,
             guard: None,
             body: expr,
             span,
             id: ast::DUMMY_NODE_ID,
+            is_placeholder: false,
         }
     }
 
     pub fn arm_unreachable(&self, span: Span) -> ast::Arm {
-        self.arm(span, vec![self.pat_wild(span)], self.expr_unreachable(span))
+        self.arm(span, self.pat_wild(span), self.expr_unreachable(span))
     }
 
     pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm>) -> P<Expr> {
@@ -701,6 +705,7 @@
             pat: arg_pat,
             span,
             ty,
+            is_placeholder: false,
         }
     }
 
@@ -774,6 +779,7 @@
                 vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 attrs: Vec::new(),
                 id: ast::DUMMY_NODE_ID,
+                is_placeholder: false,
             }
         }).collect();
 
@@ -790,6 +796,7 @@
             id: ast::DUMMY_NODE_ID,
             ident,
             span,
+            is_placeholder: false,
         }
     }
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 7b4a516..b80c530 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -26,7 +26,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use std::io::ErrorKind;
-use std::{iter, mem};
+use std::{iter, mem, slice};
 use std::ops::DerefMut;
 use std::rc::Rc;
 use std::path::PathBuf;
@@ -141,7 +141,40 @@
         "impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items;
     }
     ForeignItems(SmallVec<[ast::ForeignItem; 1]>) {
-        "foreign item"; many fn flat_map_foreign_item; fn visit_foreign_item; fn make_foreign_items;
+        "foreign item";
+        many fn flat_map_foreign_item;
+        fn visit_foreign_item;
+        fn make_foreign_items;
+    }
+    Arms(SmallVec<[ast::Arm; 1]>) {
+        "match arm"; many fn flat_map_arm; fn visit_arm; fn make_arms;
+    }
+    Fields(SmallVec<[ast::Field; 1]>) {
+        "field expression"; many fn flat_map_field; fn visit_field; fn make_fields;
+    }
+    FieldPats(SmallVec<[ast::FieldPat; 1]>) {
+        "field pattern";
+        many fn flat_map_field_pattern;
+        fn visit_field_pattern;
+        fn make_field_patterns;
+    }
+    GenericParams(SmallVec<[ast::GenericParam; 1]>) {
+        "generic parameter";
+        many fn flat_map_generic_param;
+        fn visit_generic_param;
+        fn make_generic_params;
+    }
+    Params(SmallVec<[ast::Param; 1]>) {
+        "function parameter"; many fn flat_map_param; fn visit_param; fn make_params;
+    }
+    StructFields(SmallVec<[ast::StructField; 1]>) {
+        "field";
+        many fn flat_map_struct_field;
+        fn visit_struct_field;
+        fn make_struct_fields;
+    }
+    Variants(SmallVec<[ast::Variant; 1]>) {
+        "variant"; many fn flat_map_variant; fn visit_variant; fn make_variants;
     }
 }
 
@@ -154,6 +187,21 @@
                                                                      -> AstFragment {
         let mut items = items.into_iter();
         match self {
+            AstFragmentKind::Arms =>
+                AstFragment::Arms(items.map(Annotatable::expect_arm).collect()),
+            AstFragmentKind::Fields =>
+                AstFragment::Fields(items.map(Annotatable::expect_field).collect()),
+            AstFragmentKind::FieldPats =>
+                AstFragment::FieldPats(items.map(Annotatable::expect_field_pattern).collect()),
+            AstFragmentKind::GenericParams =>
+                AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect()),
+            AstFragmentKind::Params =>
+                AstFragment::Params(items.map(Annotatable::expect_param).collect()),
+            AstFragmentKind::StructFields => AstFragment::StructFields(
+                items.map(Annotatable::expect_struct_field).collect()
+            ),
+            AstFragmentKind::Variants =>
+                AstFragment::Variants(items.map(Annotatable::expect_variant).collect()),
             AstFragmentKind::Items =>
                 AstFragment::Items(items.map(Annotatable::expect_item).collect()),
             AstFragmentKind::ImplItems =>
@@ -177,7 +225,7 @@
 
 pub struct Invocation {
     pub kind: InvocationKind,
-    fragment_kind: AstFragmentKind,
+    pub fragment_kind: AstFragmentKind,
     pub expansion_data: ExpansionData,
 }
 
@@ -482,6 +530,27 @@
             Annotatable::Expr(mut expr) => {
                 Annotatable::Expr({ cfg.visit_expr(&mut expr); expr })
             }
+            Annotatable::Arm(arm) => {
+                Annotatable::Arm(cfg.flat_map_arm(arm).pop().unwrap())
+            }
+            Annotatable::Field(field) => {
+                Annotatable::Field(cfg.flat_map_field(field).pop().unwrap())
+            }
+            Annotatable::FieldPat(fp) => {
+                Annotatable::FieldPat(cfg.flat_map_field_pattern(fp).pop().unwrap())
+            }
+            Annotatable::GenericParam(param) => {
+                Annotatable::GenericParam(cfg.flat_map_generic_param(param).pop().unwrap())
+            }
+            Annotatable::Param(param) => {
+                Annotatable::Param(cfg.flat_map_param(param).pop().unwrap())
+            }
+            Annotatable::StructField(sf) => {
+                Annotatable::StructField(cfg.flat_map_struct_field(sf).pop().unwrap())
+            }
+            Annotatable::Variant(v) => {
+                Annotatable::Variant(cfg.flat_map_variant(v).pop().unwrap())
+            }
         }
     }
 
@@ -547,6 +616,14 @@
                         Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
                         Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                         Annotatable::Expr(expr) => token::NtExpr(expr),
+                        Annotatable::Arm(..)
+                        | Annotatable::Field(..)
+                        | Annotatable::FieldPat(..)
+                        | Annotatable::GenericParam(..)
+                        | Annotatable::Param(..)
+                        | Annotatable::StructField(..)
+                        | Annotatable::Variant(..)
+                            => panic!("unexpected annotatable"),
                     })), DUMMY_SP).into();
                     let input = self.extract_proc_macro_attr_input(attr.tokens, span);
                     let tok_result = expander.expand(self.cx, span, input, item_tok);
@@ -625,6 +702,14 @@
             Annotatable::Expr(_) if self.cx.ecfg.proc_macro_hygiene() => return,
             Annotatable::Stmt(_) => ("statements", sym::proc_macro_hygiene),
             Annotatable::Expr(_) => ("expressions", sym::proc_macro_hygiene),
+            Annotatable::Arm(..)
+            | Annotatable::Field(..)
+            | Annotatable::FieldPat(..)
+            | Annotatable::GenericParam(..)
+            | Annotatable::Param(..)
+            | Annotatable::StructField(..)
+            | Annotatable::Variant(..)
+            => panic!("unexpected annotatable"),
         };
         emit_feature_err(
             self.cx.parse_sess,
@@ -681,6 +766,14 @@
             AstFragmentKind::TraitItems => return,
             AstFragmentKind::ImplItems => return,
             AstFragmentKind::ForeignItems => return,
+            AstFragmentKind::Arms
+            | AstFragmentKind::Fields
+            | AstFragmentKind::FieldPats
+            | AstFragmentKind::GenericParams
+            | AstFragmentKind::Params
+            | AstFragmentKind::StructFields
+            | AstFragmentKind::Variants
+                => panic!("unexpected AST fragment kind"),
         };
         if self.cx.ecfg.proc_macro_hygiene() {
             return
@@ -701,7 +794,7 @@
         path: &Path,
         span: Span,
     ) -> AstFragment {
-        let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
+        let mut parser = self.cx.new_parser_from_tts(toks);
         match parser.parse_ast_fragment(kind, false) {
             Ok(fragment) => {
                 parser.ensure_complete_parse(path, kind.name(), span);
@@ -771,6 +864,14 @@
             },
             AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?),
             AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat(None)?),
+            AstFragmentKind::Arms
+            | AstFragmentKind::Fields
+            | AstFragmentKind::FieldPats
+            | AstFragmentKind::GenericParams
+            | AstFragmentKind::Params
+            | AstFragmentKind::StructFields
+            | AstFragmentKind::Variants
+                => panic!("unexpected AST fragment kind"),
         })
     }
 
@@ -918,7 +1019,7 @@
     fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
         let features = self.cx.ecfg.features.unwrap();
         for attr in attrs.iter() {
-            self.check_attribute_inner(attr, features);
+            feature_gate::check_attribute(attr, self.cx.parse_sess, features);
 
             // macros are expanded before any lint passes so this warning has to be hardcoded
             if attr.path == sym::derive {
@@ -928,15 +1029,6 @@
             }
         }
     }
-
-    fn check_attribute(&mut self, at: &ast::Attribute) {
-        let features = self.cx.ecfg.features.unwrap();
-        self.check_attribute_inner(at, features);
-    }
-
-    fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) {
-        feature_gate::check_attribute(at, self.cx.parse_sess, features);
-    }
 }
 
 impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
@@ -972,6 +1064,84 @@
         });
     }
 
+    fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
+        let mut arm = configure!(self, arm);
+
+        let (attr, traits, after_derive) = self.classify_item(&mut arm);
+        if attr.is_some() || !traits.is_empty() {
+            return self.collect_attr(attr, traits, Annotatable::Arm(arm),
+                                     AstFragmentKind::Arms, after_derive)
+                                     .make_arms();
+        }
+
+        noop_flat_map_arm(arm, self)
+    }
+
+    fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
+        let mut field = configure!(self, field);
+
+        let (attr, traits, after_derive) = self.classify_item(&mut field);
+        if attr.is_some() || !traits.is_empty() {
+            return self.collect_attr(attr, traits, Annotatable::Field(field),
+                                     AstFragmentKind::Fields, after_derive)
+                                     .make_fields();
+        }
+
+        noop_flat_map_field(field, self)
+    }
+
+    fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
+        let mut fp = configure!(self, fp);
+
+        let (attr, traits, after_derive) = self.classify_item(&mut fp);
+        if attr.is_some() || !traits.is_empty() {
+            return self.collect_attr(attr, traits, Annotatable::FieldPat(fp),
+                                     AstFragmentKind::FieldPats, after_derive)
+                                     .make_field_patterns();
+        }
+
+        noop_flat_map_field_pattern(fp, self)
+    }
+
+    fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
+        let mut p = configure!(self, p);
+
+        let (attr, traits, after_derive) = self.classify_item(&mut p);
+        if attr.is_some() || !traits.is_empty() {
+            return self.collect_attr(attr, traits, Annotatable::Param(p),
+                                     AstFragmentKind::Params, after_derive)
+                                     .make_params();
+        }
+
+        noop_flat_map_param(p, self)
+    }
+
+    fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
+        let mut sf = configure!(self, sf);
+
+        let (attr, traits, after_derive) = self.classify_item(&mut sf);
+        if attr.is_some() || !traits.is_empty() {
+            return self.collect_attr(attr, traits, Annotatable::StructField(sf),
+                                     AstFragmentKind::StructFields, after_derive)
+                                     .make_struct_fields();
+        }
+
+        noop_flat_map_struct_field(sf, self)
+    }
+
+    fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
+        let mut variant = configure!(self, variant);
+
+        let (attr, traits, after_derive) = self.classify_item(&mut variant);
+        if attr.is_some() || !traits.is_empty() {
+            return self.collect_attr(attr, traits, Annotatable::Variant(variant),
+                                     AstFragmentKind::Variants, after_derive)
+                                     .make_variants();
+        }
+
+        noop_flat_map_variant(variant, self)
+    }
+
     fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
         let expr = configure!(self, expr);
         expr.filter_map(|mut expr| {
@@ -1227,12 +1397,20 @@
         }
     }
 
-   fn flat_map_generic_param(
-       &mut self,
-       param: ast::GenericParam
+    fn flat_map_generic_param(
+        &mut self,
+        param: ast::GenericParam
     ) -> SmallVec<[ast::GenericParam; 1]>
     {
-        let param = configure!(self, param);
+        let mut param = configure!(self, param);
+
+        let (attr, traits, after_derive) = self.classify_item(&mut param);
+        if attr.is_some() || !traits.is_empty() {
+            return self.collect_attr(attr, traits, Annotatable::GenericParam(param),
+                                     AstFragmentKind::GenericParams, after_derive)
+                                     .make_generic_params();
+        }
+
         noop_flat_map_generic_param(param, self)
     }
 
@@ -1258,7 +1436,7 @@
 
                 if let Some(file) = it.value_str() {
                     let err_count = self.cx.parse_sess.span_diagnostic.err_count();
-                    self.check_attribute(&at);
+                    self.check_attributes(slice::from_ref(at));
                     if self.cx.parse_sess.span_diagnostic.err_count() > err_count {
                         // avoid loading the file if they haven't enabled the feature
                         return noop_visit_attribute(at, self);
diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs
index d800cfe..52a0f95 100644
--- a/src/libsyntax/ext/placeholders.rs
+++ b/src/libsyntax/ext/placeholders.rs
@@ -32,6 +32,16 @@
         attrs: ThinVec::new(),
         node: ast::ExprKind::Mac(mac_placeholder()),
     });
+    let ty = P(ast::Ty {
+        id,
+        node: ast::TyKind::Mac(mac_placeholder()),
+        span,
+    });
+    let pat = P(ast::Pat {
+        id,
+        node: ast::PatKind::Mac(mac_placeholder()),
+        span,
+    });
 
     match kind {
         AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
@@ -67,6 +77,81 @@
             let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new()));
             ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
         }]),
+        AstFragmentKind::Arms => AstFragment::Arms(smallvec![
+            ast::Arm {
+                attrs: Default::default(),
+                body: expr_placeholder(),
+                guard: None,
+                id,
+                pat,
+                span,
+                is_placeholder: true,
+            }
+        ]),
+        AstFragmentKind::Fields => AstFragment::Fields(smallvec![
+            ast::Field {
+                attrs: Default::default(),
+                expr: expr_placeholder(),
+                id,
+                ident,
+                is_shorthand: false,
+                span,
+                is_placeholder: true,
+            }
+        ]),
+        AstFragmentKind::FieldPats => AstFragment::FieldPats(smallvec![
+            ast::FieldPat {
+                attrs: Default::default(),
+                id,
+                ident,
+                is_shorthand: false,
+                pat,
+                span,
+                is_placeholder: true,
+            }
+        ]),
+        AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{
+            ast::GenericParam {
+                attrs: Default::default(),
+                bounds: Default::default(),
+                id,
+                ident,
+                is_placeholder: true,
+                kind: ast::GenericParamKind::Lifetime,
+            }
+        }]),
+        AstFragmentKind::Params => AstFragment::Params(smallvec![
+            ast::Param {
+                attrs: Default::default(),
+                id,
+                pat,
+                span,
+                ty,
+                is_placeholder: true,
+            }
+        ]),
+        AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![
+            ast::StructField {
+                attrs: Default::default(),
+                id,
+                ident: None,
+                span,
+                ty,
+                vis,
+                is_placeholder: true,
+            }
+        ]),
+        AstFragmentKind::Variants => AstFragment::Variants(smallvec![
+            ast::Variant {
+                attrs: Default::default(),
+                data: ast::VariantData::Struct(Default::default(), false),
+                disr_expr: None,
+                id,
+                ident,
+                span,
+                is_placeholder: true,
+            }
+        ])
     }
 }
 
@@ -105,6 +190,66 @@
 }
 
 impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
+    fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
+        if arm.is_placeholder {
+            self.remove(arm.id).make_arms()
+        } else {
+            noop_flat_map_arm(arm, self)
+        }
+    }
+
+    fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
+        if field.is_placeholder {
+            self.remove(field.id).make_fields()
+        } else {
+            noop_flat_map_field(field, self)
+        }
+    }
+
+    fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
+        if fp.is_placeholder {
+            self.remove(fp.id).make_field_patterns()
+        } else {
+            noop_flat_map_field_pattern(fp, self)
+        }
+    }
+
+    fn flat_map_generic_param(
+        &mut self,
+        param: ast::GenericParam
+    ) -> SmallVec<[ast::GenericParam; 1]>
+    {
+        if param.is_placeholder {
+            self.remove(param.id).make_generic_params()
+        } else {
+            noop_flat_map_generic_param(param, self)
+        }
+    }
+
+    fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
+        if p.is_placeholder {
+            self.remove(p.id).make_params()
+        } else {
+            noop_flat_map_param(p, self)
+        }
+    }
+
+    fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
+        if sf.is_placeholder {
+            self.remove(sf.id).make_struct_fields()
+        } else {
+            noop_flat_map_struct_field(sf, self)
+        }
+    }
+
+    fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
+        if variant.is_placeholder {
+            self.remove(variant.id).make_variants()
+        } else {
+            noop_flat_map_variant(variant, self)
+        }
+    }
+
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         match item.node {
             ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
diff --git a/src/libsyntax/ext/proc_macro.rs b/src/libsyntax/ext/proc_macro.rs
index 4a44c9a..47b17ce 100644
--- a/src/libsyntax/ext/proc_macro.rs
+++ b/src/libsyntax/ext/proc_macro.rs
@@ -88,6 +88,14 @@
               item: Annotatable)
               -> Vec<Annotatable> {
         let item = match item {
+            Annotatable::Arm(..) |
+            Annotatable::Field(..) |
+            Annotatable::FieldPat(..) |
+            Annotatable::GenericParam(..) |
+            Annotatable::Param(..) |
+            Annotatable::StructField(..) |
+            Annotatable::Variant(..)
+                => panic!("unexpected annotatable"),
             Annotatable::Item(item) => item,
             Annotatable::ImplItem(_) |
             Annotatable::TraitItem(_) |
diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs
index 1a26b17..544ec78 100644
--- a/src/libsyntax/ext/proc_macro_server.rs
+++ b/src/libsyntax/ext/proc_macro_server.rs
@@ -322,8 +322,7 @@
     fn is_valid(string: &str) -> bool {
         let mut chars = string.chars();
         if let Some(start) = chars.next() {
-            (start == '_' || start.is_xid_start())
-                && chars.all(|cont| cont == '_' || cont.is_xid_continue())
+            rustc_lexer::is_id_start(start) && chars.all(rustc_lexer::is_id_continue)
         } else {
             false
         }
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 46ffa52..b27e9c5 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -877,9 +877,9 @@
         // Now `last` holds the complete set of NT tokens that could
         // end the sequence before SUFFIX. Check that every one works with `suffix`.
         'each_last: for token in &last.tokens {
-            if let TokenTree::MetaVarDecl(_, ref name, ref frag_spec) = *token {
+            if let TokenTree::MetaVarDecl(_, name, frag_spec) = *token {
                 for next_token in &suffix_first.tokens {
-                    match is_in_follow(next_token, &frag_spec.as_str()) {
+                    match is_in_follow(next_token, frag_spec.name) {
                         IsInFollow::Invalid(msg, help) => {
                             sess.span_diagnostic
                                 .struct_span_err(next_token.span(), &msg)
@@ -948,7 +948,7 @@
 
 fn token_can_be_followed_by_any(tok: &quoted::TokenTree) -> bool {
     if let quoted::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok {
-        frag_can_be_followed_by_any(&frag_spec.as_str())
+        frag_can_be_followed_by_any(frag_spec.name)
     } else {
         // (Non NT's can always be followed by anthing in matchers.)
         true
@@ -963,15 +963,15 @@
 /// specifier which consumes at most one token tree can be followed by
 /// a fragment specifier (indeed, these fragments can be followed by
 /// ANYTHING without fear of future compatibility hazards).
-fn frag_can_be_followed_by_any(frag: &str) -> bool {
+fn frag_can_be_followed_by_any(frag: Symbol) -> bool {
     match frag {
-        "item"     | // always terminated by `}` or `;`
-        "block"    | // exactly one token tree
-        "ident"    | // exactly one token tree
-        "literal"  | // exactly one token tree
-        "meta"     | // exactly one token tree
-        "lifetime" | // exactly one token tree
-        "tt" =>   // exactly one token tree
+        sym::item     | // always terminated by `}` or `;`
+        sym::block    | // exactly one token tree
+        sym::ident    | // exactly one token tree
+        sym::literal  | // exactly one token tree
+        sym::meta     | // exactly one token tree
+        sym::lifetime | // exactly one token tree
+        sym::tt =>   // exactly one token tree
             true,
 
         _ =>
@@ -993,7 +993,7 @@
 /// break macros that were relying on that binary operator as a
 /// separator.
 // when changing this do not forget to update doc/book/macros.md!
-fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
+fn is_in_follow(tok: &quoted::TokenTree, frag: Symbol) -> IsInFollow {
     use quoted::TokenTree;
 
     if let TokenTree::Token(Token { kind: token::CloseDelim(_), .. }) = *tok {
@@ -1002,17 +1002,17 @@
         IsInFollow::Yes
     } else {
         match frag {
-            "item" => {
+            sym::item => {
                 // since items *must* be followed by either a `;` or a `}`, we can
                 // accept anything after them
                 IsInFollow::Yes
             }
-            "block" => {
+            sym::block => {
                 // anything can follow block, the braces provide an easy boundary to
                 // maintain
                 IsInFollow::Yes
             }
-            "stmt" | "expr" => {
+            sym::stmt | sym::expr => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1022,7 +1022,7 @@
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            "pat" => {
+            sym::pat => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1033,7 +1033,7 @@
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            "path" | "ty" => {
+            sym::path | sym::ty => {
                 const TOKENS: &[&str] = &[
                     "`{`", "`[`", "`=>`", "`,`", "`>`", "`=`", "`:`", "`;`", "`|`", "`as`",
                     "`where`",
@@ -1061,20 +1061,20 @@
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            "ident" | "lifetime" => {
+            sym::ident | sym::lifetime => {
                 // being a single token, idents and lifetimes are harmless
                 IsInFollow::Yes
             }
-            "literal" => {
+            sym::literal => {
                 // literals may be of a single token, or two tokens (negative numbers)
                 IsInFollow::Yes
             }
-            "meta" | "tt" => {
+            sym::meta | sym::tt => {
                 // being either a single token or a delimited sequence, tt is
                 // harmless
                 IsInFollow::Yes
             }
-            "vis" => {
+            sym::vis => {
                 // Explicitly disallow `priv`, on the off chance it comes back.
                 const TOKENS: &[&str] = &["`,`", "an ident", "a type"];
                 match tok {
@@ -1099,7 +1099,7 @@
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            "" => IsInFollow::Yes, // kw::Invalid
+            kw::Invalid => IsInFollow::Yes,
             _ => IsInFollow::Invalid(
                 format!("invalid fragment specifier `{}`", frag),
                 VALID_FRAGMENT_NAMES_MSG,
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 30d5df1..2373572 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -345,8 +345,13 @@
                 LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self,
                 LockstepIterSize::Constraint(r_len, r_id) => {
                     let msg = format!(
-                        "meta-variable `{}` repeats {} times, but `{}` repeats {} times",
-                        l_id, l_len, r_id, r_len
+                        "meta-variable `{}` repeats {} time{}, but `{}` repeats {} time{}",
+                        l_id,
+                        l_len,
+                        if l_len != 1 { "s" } else { "" },
+                        r_id,
+                        r_len,
+                        if r_len != 1 { "s" } else { "" },
                     );
                     LockstepIterSize::Contradiction(msg)
                 }
diff --git a/src/libsyntax/feature_gate/accepted.rs b/src/libsyntax/feature_gate/accepted.rs
index 6c0b271..eff9f90 100644
--- a/src/libsyntax/feature_gate/accepted.rs
+++ b/src/libsyntax/feature_gate/accepted.rs
@@ -241,6 +241,8 @@
     (accepted, underscore_const_names, "1.37.0", Some(54912), None),
     /// Allows free and inherent `async fn`s, `async` blocks, and `<expr>.await` expressions.
     (accepted, async_await, "1.39.0", Some(50547), None),
+    /// Allows mixing bind-by-move in patterns and references to those identifiers in guards.
+    (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs
index c947b09..dd78777 100644
--- a/src/libsyntax/feature_gate/active.rs
+++ b/src/libsyntax/feature_gate/active.rs
@@ -1,9 +1,11 @@
 //! List of the active feature gates.
 
+use super::{State, Feature};
+
 use crate::edition::Edition;
 use crate::symbol::{Symbol, sym};
+
 use syntax_pos::Span;
-use super::{State, Feature};
 
 macro_rules! set {
     ($field: ident) => {{
@@ -37,9 +39,9 @@
         /// A set of features to be used by later passes.
         #[derive(Clone)]
         pub struct Features {
-            /// `#![feature]` attrs for language features, for error reporting
+            /// `#![feature]` attrs for language features, for error reporting.
             pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
-            /// `#![feature]` attrs for non-language (library) features
+            /// `#![feature]` attrs for non-language (library) features.
             pub declared_lib_features: Vec<(Symbol, Span)>,
             $(
                 $(#[doc = $doc])*
@@ -66,11 +68,11 @@
 }
 
 impl Feature {
-    /// Set this feature in `Features`. Panics if called on a non-active feature.
+    /// Sets this feature in `Features`. Panics if called on a non-active feature.
     pub fn set(&self, features: &mut Features, span: Span) {
         match self.state {
             State::Active { set } => set(features, span),
-            _ => panic!("Called `set` on feature `{}` which is not `active`", self.name)
+            _ => panic!("called `set` on feature `{}` which is not `active`", self.name)
         }
     }
 }
@@ -120,12 +122,6 @@
     /// macros disappear).
     (active, allow_internal_unsafe, "1.0.0", None, None),
 
-    /// Allows using the macros:
-    /// + `__diagnostic_used`
-    /// + `__register_diagnostic`
-    /// +`__build_diagnostic_array`
-    (active, rustc_diagnostic_macros, "1.0.0", None, None),
-
     /// Allows using `#[rustc_const_unstable(feature = "foo", ..)]` which
     /// lets a function to be `const` when opted into with `#![feature(foo)]`.
     (active, rustc_const_unstable, "1.0.0", None, None),
@@ -465,9 +461,6 @@
     /// Allows non-builtin attributes in inner attribute position.
     (active, custom_inner_attributes, "1.30.0", Some(54726), None),
 
-    /// Allows mixing bind-by-move in patterns and references to those identifiers in guards.
-    (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None),
-
     /// Allows `impl Trait` in bindings (`let`, `const`, `static`).
     (active, impl_trait_in_bindings, "1.30.0", Some(63065), None),
 
@@ -478,7 +471,7 @@
     (active, precise_pointer_size_matching, "1.32.0", Some(56354), None),
 
     /// Allows relaxing the coherence rules such that
-    /// `impl<T> ForeignTrait<LocalType> for ForeignType<T> is permitted.
+    /// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
     (active, re_rebalance_coherence, "1.32.0", Some(55437), None),
 
     /// Allows using `#[ffi_returns_twice]` on foreign functions.
@@ -520,7 +513,7 @@
     /// Allows `async || body` closures.
     (active, async_closure, "1.37.0", Some(62290), None),
 
-    /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests
+    /// Allows the use of `#[cfg(doctest)]`; set when rustdoc is collecting doctests.
     (active, cfg_doctest, "1.37.0", Some(62210), None),
 
     /// Allows `[x; N]` where `x` is a constant (RFC 2203).
@@ -529,7 +522,7 @@
     /// Allows `impl Trait` to be used inside type aliases (RFC 2515).
     (active, type_alias_impl_trait, "1.38.0", Some(63063), None),
 
-    /// Allows the use of or-patterns, e.g. `0 | 1`.
+    /// Allows the use of or-patterns (e.g., `0 | 1`).
     (active, or_patterns, "1.38.0", Some(54883), None),
 
     // -------------------------------------------------------------------------
diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs
index ee7ac3b..b6e1320 100644
--- a/src/libsyntax/feature_gate/builtin_attrs.rs
+++ b/src/libsyntax/feature_gate/builtin_attrs.rs
@@ -79,6 +79,7 @@
     CrateLevel,
 }
 
+#[derive(Clone, Copy)]
 pub enum AttributeGate {
     /// Is gated by a given feature gate, reason
     /// and function to check if enabled
@@ -169,7 +170,7 @@
 
 pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate);
 
-/// Attributes that have a special meaning to rustc or rustdoc
+/// Attributes that have a special meaning to rustc or rustdoc.
 pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // ==========================================================================
     // Stable attributes:
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs
index f3a9d13..b4491a8 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/libsyntax/feature_gate/check.rs
@@ -1,7 +1,7 @@
 use super::{active::{ACTIVE_FEATURES, Features}, Feature, State as FeatureState};
 use super::accepted::ACCEPTED_FEATURES;
 use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
-use super::builtin_attrs::{AttributeGate, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
+use super::builtin_attrs::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
 
 use crate::ast::{
     self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind,
@@ -32,16 +32,10 @@
     Deprecated(&'static str, Option<&'static str>),
 }
 
-struct Context<'a> {
-    features: &'a Features,
-    parse_sess: &'a ParseSess,
-    plugin_attributes: &'a [(Symbol, AttributeType)],
-}
-
 macro_rules! gate_feature_fn {
     ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
         let (cx, has_feature, span,
-             name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
+             name, explain, level) = (&*$cx, $has_feature, $span, $name, $explain, $level);
         let has_feature: bool = has_feature(&$cx.features);
         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
         if !has_feature && !span.allows_unstable($name) {
@@ -62,68 +56,8 @@
     };
 }
 
-impl<'a> Context<'a> {
-    fn check_attribute(
-        &self,
-        attr: &ast::Attribute,
-        attr_info: Option<&BuiltinAttribute>,
-        is_macro: bool
-    ) {
-        debug!("check_attribute(attr = {:?})", attr);
-        if let Some(&(name, ty, _template, ref gateage)) = attr_info {
-            if let AttributeGate::Gated(_, name, desc, ref has_feature) = *gateage {
-                if !attr.span.allows_unstable(name) {
-                    gate_feature_fn!(
-                        self, has_feature, attr.span, name, desc, GateStrength::Hard
-                    );
-                }
-            } else if name == sym::doc {
-                if let Some(content) = attr.meta_item_list() {
-                    if content.iter().any(|c| c.check_name(sym::include)) {
-                        gate_feature!(self, external_doc, attr.span,
-                            "`#[doc(include = \"...\")]` is experimental"
-                        );
-                    }
-                }
-            }
-            debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
-            return;
-        } else {
-            for segment in &attr.path.segments {
-                if segment.ident.as_str().starts_with("rustc") {
-                    let msg = "attributes starting with `rustc` are \
-                               reserved for use by the `rustc` compiler";
-                    gate_feature!(self, rustc_attrs, segment.ident.span, msg);
-                }
-            }
-        }
-        for &(n, ty) in self.plugin_attributes {
-            if attr.path == n {
-                // Plugins can't gate attributes, so we don't check for it
-                // unlike the code above; we only use this loop to
-                // short-circuit to avoid the checks below.
-                debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
-                return;
-            }
-        }
-        if !is_macro && !attr::is_known(attr) {
-            // Only run the custom attribute lint during regular feature gate
-            // checking. Macro gating runs before the plugin attributes are
-            // registered, so we skip this in that case.
-            let msg = format!("the attribute `{}` is currently unknown to the compiler and \
-                               may have meaning added to it in the future", attr.path);
-            gate_feature!(self, custom_attribute, attr.span, &msg);
-        }
-    }
-}
-
-pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
-    let cx = Context { features, parse_sess, plugin_attributes: &[] };
-    cx.check_attribute(
-        attr,
-        attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name).map(|a| *a)),
-        true
-    );
+crate fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
+    PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
 }
 
 fn find_lang_feature_issue(feature: Symbol) -> Option<u32> {
@@ -238,21 +172,21 @@
     "unsized tuple coercion is not stable enough for use and is subject to change";
 
 struct PostExpansionVisitor<'a> {
-    context: &'a Context<'a>,
-    builtin_attributes: &'static FxHashMap<Symbol, &'static BuiltinAttribute>,
+    parse_sess: &'a ParseSess,
+    features: &'a Features,
 }
 
 macro_rules! gate_feature_post {
     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
         let (cx, span) = ($cx, $span);
         if !span.allows_unstable(sym::$feature) {
-            gate_feature!(cx.context, $feature, span, $explain)
+            gate_feature!(cx, $feature, span, $explain)
         }
     }};
     ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
         let (cx, span) = ($cx, $span);
         if !span.allows_unstable(sym::$feature) {
-            gate_feature!(cx.context, $feature, span, $explain, $level)
+            gate_feature!(cx, $feature, span, $explain, $level)
         }
     }}
 }
@@ -316,50 +250,44 @@
 
 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
-        let attr_info = attr.ident().and_then(|ident| {
-            self.builtin_attributes.get(&ident.name).map(|a| *a)
-        });
-
-        // Check for gated attributes.
-        self.context.check_attribute(attr, attr_info, false);
-
-        if attr.check_name(sym::doc) {
-            if let Some(content) = attr.meta_item_list() {
-                if content.len() == 1 && content[0].check_name(sym::cfg) {
-                    gate_feature_post!(&self, doc_cfg, attr.span,
-                        "`#[doc(cfg(...))]` is experimental"
-                    );
-                } else if content.iter().any(|c| c.check_name(sym::masked)) {
-                    gate_feature_post!(&self, doc_masked, attr.span,
-                        "`#[doc(masked)]` is experimental"
-                    );
-                } else if content.iter().any(|c| c.check_name(sym::spotlight)) {
-                    gate_feature_post!(&self, doc_spotlight, attr.span,
-                        "`#[doc(spotlight)]` is experimental"
-                    );
-                } else if content.iter().any(|c| c.check_name(sym::alias)) {
-                    gate_feature_post!(&self, doc_alias, attr.span,
-                        "`#[doc(alias = \"...\")]` is experimental"
-                    );
-                } else if content.iter().any(|c| c.check_name(sym::keyword)) {
-                    gate_feature_post!(&self, doc_keyword, attr.span,
-                        "`#[doc(keyword = \"...\")]` is experimental"
-                    );
-                }
-            }
+        let attr_info =
+            attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);
+        // Check feature gates for built-in attributes.
+        if let Some((.., AttributeGate::Gated(_, name, descr, has_feature))) = attr_info {
+            gate_feature_fn!(self, has_feature, attr.span, name, descr, GateStrength::Hard);
         }
-
+        // Check input tokens for built-in and key-value attributes.
         match attr_info {
             // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
-            Some(&(name, _, template, _)) if name != sym::rustc_dummy =>
-                check_builtin_attribute(self.context.parse_sess, attr, name, template),
+            Some((name, _, template, _)) if name != sym::rustc_dummy =>
+                check_builtin_attribute(self.parse_sess, attr, name, template),
             _ => if let Some(TokenTree::Token(token)) = attr.tokens.trees().next() {
                 if token == token::Eq {
                     // All key-value attributes are restricted to meta-item syntax.
-                    attr.parse_meta(self.context.parse_sess).map_err(|mut err| err.emit()).ok();
+                    attr.parse_meta(self.parse_sess).map_err(|mut err| err.emit()).ok();
                 }
             }
         }
+        // Check unstable flavors of the `#[doc]` attribute.
+        if attr.check_name(sym::doc) {
+            for nested_meta in attr.meta_item_list().unwrap_or_default() {
+                macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
+                    $(if nested_meta.check_name(sym::$name) {
+                        let msg = concat!("`#[doc(", stringify!($name), ")]` is experimental");
+                        gate_feature!(self, $feature, attr.span, msg);
+                    })*
+                }}
+
+                gate_doc!(
+                    include => external_doc
+                    cfg => doc_cfg
+                    masked => doc_masked
+                    spotlight => doc_spotlight
+                    alias => doc_alias
+                    keyword => doc_keyword
+                );
+            }
+        }
     }
 
     fn visit_name(&mut self, sp: Span, name: ast::Name) {
@@ -367,7 +295,7 @@
             gate_feature_post!(
                 &self,
                 non_ascii_idents,
-                self.context.parse_sess.source_map().def_span(sp),
+                self.parse_sess.source_map().def_span(sp),
                 "non-ascii idents are not fully supported"
             );
         }
@@ -423,12 +351,9 @@
                     }
                 }
 
-                let has_feature = self.context.features.arbitrary_enum_discriminant;
+                let has_feature = self.features.arbitrary_enum_discriminant;
                 if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
-                    Parser::maybe_report_invalid_custom_discriminants(
-                        self.context.parse_sess,
-                        &variants,
-                    );
+                    Parser::maybe_report_invalid_custom_discriminants(self.parse_sess, &variants);
                 }
             }
 
@@ -538,7 +463,7 @@
             ast::ExprKind::Type(..) => {
                 // To avoid noise about type ascription in common syntax errors, only emit if it
                 // is the *only* error.
-                if self.context.parse_sess.span_diagnostic.err_count() == 0 {
+                if self.parse_sess.span_diagnostic.err_count() == 0 {
                     gate_feature_post!(&self, type_ascription, e.span,
                                        "type ascription is experimental");
                 }
@@ -872,22 +797,17 @@
 }
 
 pub fn check_crate(krate: &ast::Crate,
-                   sess: &ParseSess,
+                   parse_sess: &ParseSess,
                    features: &Features,
-                   plugin_attributes: &[(Symbol, AttributeType)],
                    unstable: UnstableFeatures) {
-    maybe_stage_features(&sess.span_diagnostic, krate, unstable);
-    let ctx = Context {
-        features,
-        parse_sess: sess,
-        plugin_attributes,
-    };
+    maybe_stage_features(&parse_sess.span_diagnostic, krate, unstable);
+    let mut visitor = PostExpansionVisitor { parse_sess, features };
 
     macro_rules! gate_all {
         ($gate:ident, $msg:literal) => { gate_all!($gate, $gate, $msg); };
         ($spans:ident, $gate:ident, $msg:literal) => {
-            for span in &*sess.gated_spans.$spans.borrow() {
-                gate_feature!(&ctx, $gate, *span, $msg);
+            for span in &*parse_sess.gated_spans.$spans.borrow() {
+                gate_feature!(&visitor, $gate, *span, $msg);
             }
         }
     }
@@ -898,11 +818,7 @@
     gate_all!(yields, generators, "yield syntax is experimental");
     gate_all!(or_patterns, "or-patterns syntax is experimental");
 
-    let visitor = &mut PostExpansionVisitor {
-        context: &ctx,
-        builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP,
-    };
-    visit::walk_crate(visitor, krate);
+    visit::walk_crate(&mut visitor, krate);
 }
 
 #[derive(Clone, Copy, Hash)]
@@ -920,9 +836,9 @@
 
 impl UnstableFeatures {
     pub fn from_environment() -> UnstableFeatures {
-        // Whether this is a feature-staged build, i.e., on the beta or stable channel
+        // `true` if this is a feature-staged build, i.e., on the beta or stable channel.
         let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
-        // Whether we should enable unstable features for bootstrapping
+        // `true` if we should enable unstable features for bootstrapping.
         let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
         match (disable_unstable_features, bootstrap) {
             (_, true) => UnstableFeatures::Cheat,
diff --git a/src/libsyntax/feature_gate/mod.rs b/src/libsyntax/feature_gate/mod.rs
index 1e41667..ca13ab3 100644
--- a/src/libsyntax/feature_gate/mod.rs
+++ b/src/libsyntax/feature_gate/mod.rs
@@ -58,7 +58,8 @@
     deprecated_attributes, is_builtin_attr,  is_builtin_attr_name,
 };
 pub use check::{
-    check_attribute, check_crate, get_features, feature_err, emit_feature_err,
+    check_crate, get_features, feature_err, emit_feature_err,
     Stability, GateIssue, UnstableFeatures,
     EXPLAIN_STMT_ATTR_SYNTAX, EXPLAIN_UNSIZED_TUPLE_COERCION,
 };
+crate use check::check_attribute;
diff --git a/src/libsyntax/feature_gate/removed.rs b/src/libsyntax/feature_gate/removed.rs
index ad7d69b..2c29e1e 100644
--- a/src/libsyntax/feature_gate/removed.rs
+++ b/src/libsyntax/feature_gate/removed.rs
@@ -94,6 +94,11 @@
     /// Allows defining `existential type`s.
     (removed, existential_type, "1.38.0", Some(63063), None,
      Some("removed in favor of `#![feature(type_alias_impl_trait)]`")),
+    /// Allows using the macros:
+    /// + `__diagnostic_used`
+    /// + `__register_diagnostic`
+    /// +`__build_diagnostic_array`
+    (removed, rustc_diagnostic_macros, "1.38.0", None, None, None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: removed features
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 1741932..aaf6f3e 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -7,7 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
 
-#![feature(bind_by_move_pattern_guards)]
+#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))]
 #![feature(box_syntax)]
 #![feature(const_fn)]
 #![feature(const_transmute)]
@@ -18,7 +18,6 @@
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
-#![feature(rustc_diagnostic_macros)]
 #![feature(try_trait)]
 #![feature(unicode_internals)]
 
@@ -123,11 +122,8 @@
 pub mod diagnostics {
     #[macro_use]
     pub mod macros;
-    pub mod plugin;
 }
 
-// N.B., this module needs to be declared first so diagnostics are
-// registered before they are used.
 pub mod error_codes;
 
 pub mod util {
@@ -182,5 +178,3 @@
 }
 
 pub mod early_buffered_lints;
-
-__build_diagnostic_array! { libsyntax, DIAGNOSTICS }
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index e14ca4b..5a37222 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -1,10 +1,10 @@
-//! A MutVisitor represents an AST modification; it accepts an AST piece and
-//! and mutates it in place. So, for instance, macro expansion is a MutVisitor
+//! A `MutVisitor` represents an AST modification; it accepts an AST piece and
+//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor`
 //! that walks over an AST and modifies it.
 //!
-//! Note: using a MutVisitor (other than the MacroExpander MutVisitor) on
+//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on
 //! an AST before macro expansion is probably a bad idea. For instance,
-//! a MutVisitor renaming item names in a module will miss all of those
+//! a `MutVisitor` renaming item names in a module will miss all of those
 //! that are created by the expansion of a macro.
 
 use crate::ast::*;
@@ -370,6 +370,7 @@
         attrs,
         id,
         ident,
+        is_placeholder: _,
         is_shorthand: _,
         pat,
         span,
@@ -402,14 +403,11 @@
     vis.visit_span(span);
 }
 
-pub fn noop_flat_map_arm<T: MutVisitor>(
-    mut arm: Arm,
-    vis: &mut T,
-) -> SmallVec<[Arm; 1]> {
-    let Arm { attrs, pats, guard, body, span, id } = &mut arm;
+pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
+    let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
     visit_attrs(attrs, vis);
     vis.visit_id(id);
-    visit_vec(pats, |pat| vis.visit_pat(pat));
+    vis.visit_pat(pat);
     visit_opt(guard, |guard| vis.visit_expr(guard));
     vis.visit_expr(body);
     vis.visit_span(span);
@@ -480,7 +478,7 @@
 pub fn noop_flat_map_variant<T: MutVisitor>(mut variant: Variant, vis: &mut T)
     -> SmallVec<[Variant; 1]>
 {
-    let Variant { ident, attrs, id, data, disr_expr, span } = &mut variant;
+    let Variant { ident, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
     vis.visit_ident(ident);
     visit_attrs(attrs, vis);
     vis.visit_id(id);
@@ -588,7 +586,7 @@
 }
 
 pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> SmallVec<[Param; 1]> {
-    let Param { attrs, id, pat, span, ty } = &mut param;
+    let Param { attrs, id, pat, span, ty, is_placeholder: _ } = &mut param;
     vis.visit_id(id);
     visit_thin_attrs(attrs, vis);
     vis.visit_pat(pat);
@@ -617,7 +615,7 @@
     })
 }
 
-// Apply ident visitor if it's an ident, apply other visits to interpolated nodes.
+// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
 // In practice the ident part is not actually used by specific visitors right now,
 // but there's a test below checking that it works.
 pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
@@ -628,7 +626,7 @@
             vis.visit_ident(&mut ident);
             *name = ident.name;
             *span = ident.span;
-            return; // avoid visiting the span for the second time
+            return; // Avoid visiting the span for the second time.
         }
         token::Interpolated(nt) => {
             let mut nt = Lrc::make_mut(nt);
@@ -639,28 +637,28 @@
     vis.visit_span(span);
 }
 
-/// Apply visitor to elements of interpolated nodes.
+/// Applies the visitor to elements of interpolated nodes.
 //
 // N.B., this can occur only when applying a visitor to partially expanded
 // code, where parsed pieces have gotten implanted ito *other* macro
 // invocations. This is relevant for macro hygiene, but possibly not elsewhere.
 //
 // One problem here occurs because the types for flat_map_item, flat_map_stmt,
-// etc. allow the visitor to return *multiple* items; this is a problem for the
+// etc., allow the visitor to return *multiple* items; this is a problem for the
 // nodes here, because they insist on having exactly one piece. One solution
 // would be to mangle the MutVisitor trait to include one-to-many and
 // one-to-one versions of these entry points, but that would probably confuse a
 // lot of people and help very few. Instead, I'm just going to put in dynamic
 // checks. I think the performance impact of this will be pretty much
-// nonexistent. The danger is that someone will apply a MutVisitor to a
+// nonexistent. The danger is that someone will apply a `MutVisitor` to a
 // partially expanded node, and will be confused by the fact that their
-// "flat_map_item" or "flat_map_stmt" isn't getting called on NtItem or NtStmt
+// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt`
 // nodes. Hopefully they'll wind up reading this comment, and doing something
 // appropriate.
 //
-// BTW, design choice: I considered just changing the type of, e.g., NtItem to
+// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to
 // contain multiple items, but decided against it when I looked at
-// parse_item_or_view_item and tried to figure out what I would do with
+// `parse_item_or_view_item` and tried to figure out what I would do with
 // multiple items there....
 pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
     match nt {
@@ -739,7 +737,7 @@
     vis: &mut T
 ) -> SmallVec<[GenericParam; 1]>
 {
-    let GenericParam { id, ident, attrs, bounds, kind } = &mut param;
+    let GenericParam { id, ident, attrs, bounds, kind, is_placeholder: _ } = &mut param;
     vis.visit_id(id);
     vis.visit_ident(ident);
     visit_thin_attrs(attrs, vis);
@@ -831,7 +829,7 @@
 pub fn noop_flat_map_struct_field<T: MutVisitor>(mut sf: StructField, visitor: &mut T)
     -> SmallVec<[StructField; 1]>
 {
-    let StructField { span, ident, vis, id, ty, attrs } = &mut sf;
+    let StructField { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut sf;
     visitor.visit_span(span);
     visit_opt(ident, |ident| visitor.visit_ident(ident));
     visitor.visit_vis(vis);
@@ -842,7 +840,7 @@
 }
 
 pub fn noop_flat_map_field<T: MutVisitor>(mut f: Field, vis: &mut T) -> SmallVec<[Field; 1]> {
-    let Field { ident, expr, span, is_shorthand: _, attrs, id } = &mut f;
+    let Field { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f;
     vis.visit_ident(ident);
     vis.visit_expr(expr);
     vis.visit_id(id);
@@ -1017,7 +1015,7 @@
     });
 }
 
-// Mutate one item into possibly many items.
+// Mutates one item into possibly many items.
 pub fn noop_flat_map_item<T: MutVisitor>(mut item: P<Item>, visitor: &mut T)
                                          -> SmallVec<[P<Item>; 1]> {
     let Item { ident, attrs, id, node, vis, span, tokens: _ } = item.deref_mut();
@@ -1132,8 +1130,8 @@
             vis.visit_ty(ty);
         }
         ExprKind::AddrOf(_m, ohs) => vis.visit_expr(ohs),
-        ExprKind::Let(pats, scrutinee) => {
-            visit_vec(pats, |pat| vis.visit_pat(pat));
+        ExprKind::Let(pat, scrutinee) => {
+            vis.visit_pat(pat);
             vis.visit_expr(scrutinee);
         }
         ExprKind::If(cond, tr, fl) => {
@@ -1227,7 +1225,7 @@
         ExprKind::Paren(expr) => {
             vis.visit_expr(expr);
 
-            // Nodes that are equal modulo `Paren` sugar no-ops should have the same ids.
+            // Nodes that are equal modulo `Paren` sugar no-ops should have the same IDs.
             *id = expr.id;
             vis.visit_span(span);
             visit_thin_attrs(attrs, vis);
diff --git a/src/libsyntax/mut_visit/tests.rs b/src/libsyntax/mut_visit/tests.rs
index 6868736..f779e0d 100644
--- a/src/libsyntax/mut_visit/tests.rs
+++ b/src/libsyntax/mut_visit/tests.rs
@@ -6,13 +6,13 @@
 use crate::mut_visit;
 use crate::with_default_globals;
 
-// this version doesn't care about getting comments or docstrings in.
+// This version doesn't care about getting comments or doc-strings in.
 fn fake_print_crate(s: &mut pprust::State<'_>,
                     krate: &ast::Crate) {
     s.print_mod(&krate.module, &krate.attrs)
 }
 
-// change every identifier to "zz"
+// Change every identifier to "zz".
 struct ToZzIdentMutVisitor;
 
 impl MutVisitor for ToZzIdentMutVisitor {
@@ -24,7 +24,7 @@
     }
 }
 
-// maybe add to expand.rs...
+// Maybe add to `expand.rs`.
 macro_rules! assert_pred {
     ($pred:expr, $predname:expr, $a:expr , $b:expr) => (
         {
@@ -39,7 +39,7 @@
     )
 }
 
-// make sure idents get transformed everywhere
+// Make sure idents get transformed everywhere.
 #[test] fn ident_transformation () {
     with_default_globals(|| {
         let mut zz_visitor = ToZzIdentMutVisitor;
@@ -54,7 +54,7 @@
     })
 }
 
-// even inside macro defs....
+// Make sure idents get transformed even inside macro defs.
 #[test] fn ident_transformation_in_defs () {
     with_default_globals(|| {
         let mut zz_visitor = ToZzIdentMutVisitor;
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 6711782..9aa1ec0 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -26,7 +26,7 @@
         Ok(attrs)
     }
 
-    /// Parse attributes that appear before an item
+    /// Parses attributes that appear before an item.
     crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
         let mut attrs: Vec<ast::Attribute> = Vec::new();
         let mut just_parsed_doc_comment = false;
@@ -69,10 +69,10 @@
         Ok(attrs)
     }
 
-    /// Matches `attribute = # ! [ meta_item ]`
+    /// Matches `attribute = # ! [ meta_item ]`.
     ///
-    /// If permit_inner is true, then a leading `!` indicates an inner
-    /// attribute
+    /// If `permit_inner` is `true`, then a leading `!` indicates an inner
+    /// attribute.
     pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> {
         debug!("parse_attribute: permit_inner={:?} self.token={:?}",
                permit_inner,
@@ -167,16 +167,16 @@
         })
     }
 
-    /// Parse an inner part of attribute - path and following tokens.
+    /// Parses an inner part of an attribute (the path and following tokens).
     /// The tokens must be either a delimited token stream, or empty token stream,
     /// or the "legacy" key-value form.
-    /// PATH `(` TOKEN_STREAM `)`
-    /// PATH `[` TOKEN_STREAM `]`
-    /// PATH `{` TOKEN_STREAM `}`
-    /// PATH
-    /// PATH `=` TOKEN_TREE
+    ///     PATH `(` TOKEN_STREAM `)`
+    ///     PATH `[` TOKEN_STREAM `]`
+    ///     PATH `{` TOKEN_STREAM `}`
+    ///     PATH
+    ///     PATH `=` TOKEN_TREE
     /// The delimiters or `=` are still put into the resulting token stream.
-    crate fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
+    pub fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
         let meta = match self.token.kind {
             token::Interpolated(ref nt) => match **nt {
                 Nonterminal::NtMeta(ref meta) => Some(meta.clone()),
@@ -217,11 +217,11 @@
         })
     }
 
-    /// Parse attributes that appear after the opening of an item. These should
+    /// Parses attributes that appear after the opening of an item. These should
     /// be preceded by an exclamation mark, but we accept and warn about one
     /// terminated by a semicolon.
-
-    /// matches inner_attrs*
+    ///
+    /// Matches `inner_attrs*`.
     crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
         let mut attrs: Vec<ast::Attribute> = vec![];
         loop {
@@ -237,7 +237,7 @@
                     attrs.push(attr);
                 }
                 token::DocComment(s) => {
-                    // we need to get the position of this token before we bump.
+                    // We need to get the position of this token before we bump.
                     let attr = attr::mk_sugared_doc_attr(s, self.token.span);
                     if attr.style == ast::AttrStyle::Inner {
                         attrs.push(attr);
@@ -268,10 +268,10 @@
         Ok(lit)
     }
 
-    /// Per RFC#1559, matches the following grammar:
+    /// Matches the following grammar (per RFC 1559).
     ///
-    /// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
-    /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
+    ///     meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
+    ///     meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
     pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
         let nt_meta = match self.token.kind {
             token::Interpolated(ref nt) => match **nt {
@@ -303,7 +303,7 @@
         })
     }
 
-    /// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;
+    /// Matches `meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;`.
     fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
         match self.parse_unsuffixed_lit() {
             Ok(lit) => {
@@ -324,7 +324,7 @@
         Err(self.diagnostic().struct_span_err(self.token.span, &msg))
     }
 
-    /// matches meta_seq = ( COMMASEP(meta_item_inner) )
+    /// Matches `meta_seq = ( COMMASEP(meta_item_inner) )`.
     fn parse_meta_seq(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
         self.parse_seq_to_end(&token::CloseDelim(token::Paren),
                               SeqSep::trailing_allowed(token::Comma),
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index d4e661d..b74f249 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -29,7 +29,14 @@
         span: ident.span,
         id: ast::DUMMY_NODE_ID
     };
-    Param { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, span: ident.span, ty: P(ty) }
+    Param {
+        attrs: ThinVec::default(),
+        id: ast::DUMMY_NODE_ID,
+        pat,
+        span: ident.span,
+        ty: P(ty),
+        is_placeholder: false,
+    }
 }
 
 pub enum Error {
@@ -240,7 +247,7 @@
     ) -> PResult<'a, bool /* recovered */> {
         fn tokens_to_string(tokens: &[TokenType]) -> String {
             let mut i = tokens.iter();
-            // This might be a sign we need a connect method on Iterator.
+            // This might be a sign we need a connect method on `Iterator`.
             let b = i.next()
                      .map_or(String::new(), |t| t.to_string());
             i.enumerate().fold(b, |mut b, (i, a)| {
@@ -301,7 +308,7 @@
             );
         }
         let sp = if self.token == token::Eof {
-            // This is EOF, don't want to point at the following char, but rather the last token
+            // This is EOF; don't want to point at the following char, but rather the last token.
             self.prev_span
         } else {
             label_sp
@@ -317,9 +324,9 @@
         }
 
         let is_semi_suggestable = expected.iter().any(|t| match t {
-            TokenType::Token(token::Semi) => true, // we expect a `;` here
+            TokenType::Token(token::Semi) => true, // We expect a `;` here.
             _ => false,
-        }) && ( // a `;` would be expected before the current keyword
+        }) && ( // A `;` would be expected before the current keyword.
             self.token.is_keyword(kw::Break) ||
             self.token.is_keyword(kw::Continue) ||
             self.token.is_keyword(kw::For) ||
@@ -541,16 +548,16 @@
         }
     }
 
-    /// Produce an error if comparison operators are chained (RFC #558).
-    /// We only need to check lhs, not rhs, because all comparison ops
-    /// have same precedence and are left-associative
-    crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) {
+    /// Produces an error if comparison operators are chained (RFC #558).
+    /// We only need to check the LHS, not the RHS, because all comparison ops
+    /// have same precedence and are left-associative.
+    crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> {
         debug_assert!(outer_op.is_comparison(),
                       "check_no_chained_comparison: {:?} is not comparison",
                       outer_op);
         match lhs.node {
             ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
-                // respan to include both operators
+                // Respan to include both operators.
                 let op_span = op.span.to(self.token.span);
                 let mut err = self.struct_span_err(
                     op_span,
@@ -563,11 +570,14 @@
                     err.help(
                         "use `::<...>` instead of `<...>` if you meant to specify type arguments");
                     err.help("or use `(...)` if you meant to specify fn arguments");
+                    // These cases cause too many knock-down errors, bail out (#61329).
+                    return Err(err);
                 }
                 err.emit();
             }
             _ => {}
         }
+        Ok(())
     }
 
     crate fn maybe_report_ambiguous_plus(
@@ -688,9 +698,9 @@
         Ok(())
     }
 
-    /// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`.
-    /// Attempt to convert the base expression/pattern/type into a type, parse the `::AssocItem`
-    /// tail, and combine them into a `<Ty>::AssocItem` expression/pattern/type.
+    /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
+    /// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem`
+    /// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type.
     crate fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
         &mut self,
         base: P<T>,
@@ -705,8 +715,8 @@
         Ok(base)
     }
 
-    /// Given an already parsed `Ty` parse the `::AssocItem` tail and
-    /// combine them into a `<Ty>::AssocItem` expression/pattern/type.
+    /// Given an already parsed `Ty`, parses the `::AssocItem` tail and
+    /// combines them into a `<Ty>::AssocItem` expression/pattern/type.
     crate fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
         &mut self,
         ty_span: Span,
@@ -727,7 +737,7 @@
         self.diagnostic()
             .struct_span_err(path.span, "missing angle brackets in associated item path")
             .span_suggestion(
-                // this is a best-effort recovery
+                // This is a best-effort recovery.
                 path.span,
                 "try",
                 format!("<{}>::{}", ty_str, path),
@@ -735,7 +745,7 @@
             )
             .emit();
 
-        let path_span = ty_span.shrink_to_hi(); // use an empty path since `position` == 0
+        let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
         Ok(P(T::recovered(
             Some(QSelf {
                 ty,
@@ -758,8 +768,8 @@
             if !items.is_empty() {
                 let previous_item = &items[items.len() - 1];
                 let previous_item_kind_name = match previous_item.node {
-                    // say "braced struct" because tuple-structs and
-                    // braceless-empty-struct declarations do take a semicolon
+                    // Say "braced struct" because tuple-structs and
+                    // braceless-empty-struct declarations do take a semicolon.
                     ItemKind::Struct(..) => Some("braced struct"),
                     ItemKind::Enum(..) => Some("enum"),
                     ItemKind::Trait(..) => Some("trait"),
@@ -780,7 +790,7 @@
         }
     }
 
-    /// Create a `DiagnosticBuilder` for an unexpected token `t` and try to recover if it is a
+    /// Creates a `DiagnosticBuilder` for an unexpected token `t` and tries to recover if it is a
     /// closing delimiter.
     pub fn unexpected_try_recover(
         &mut self,
@@ -838,7 +848,7 @@
         extern_sp: Span,
     ) -> PResult<'a, ()> {
         if self.token != token::Semi {
-            // this might be an incorrect fn definition (#62109)
+            // This might be an incorrect fn definition (#62109).
             let parser_snapshot = self.clone();
             match self.parse_inner_attrs_and_block() {
                 Ok((_, body)) => {
@@ -868,7 +878,7 @@
         Ok(())
     }
 
-    /// Consume alternative await syntaxes like `await!(<expr>)`, `await <expr>`,
+    /// Consumes alternative await syntaxes like `await!(<expr>)`, `await <expr>`,
     /// `await? <expr>`, `await(<expr>)`, and `await { <expr> }`.
     crate fn parse_incorrect_await_syntax(
         &mut self,
@@ -921,7 +931,7 @@
         sp
     }
 
-    /// If encountering `future.await()`, consume and emit error.
+    /// If encountering `future.await()`, consumes and emits an error.
     crate fn recover_from_await_method_call(&mut self) {
         if self.token == token::OpenDelim(token::Paren) &&
             self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren))
@@ -941,7 +951,7 @@
         }
     }
 
-    /// Recover a situation like `for ( $pat in $expr )`
+    /// Recovers a situation like `for ( $pat in $expr )`
     /// and suggest writing `for $pat in $expr` instead.
     ///
     /// This should be called before parsing the `$block`.
@@ -1007,7 +1017,7 @@
             Ok(x) => x,
             Err(mut err) => {
                 err.emit();
-                // recover from parse error
+                // Recover from parse error.
                 self.consume_block(delim);
                 self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new())
             }
@@ -1020,7 +1030,7 @@
         mut err: DiagnosticBuilder<'a>,
     ) -> PResult<'a, bool> {
         let mut pos = None;
-        // we want to use the last closing delim that would apply
+        // We want to use the last closing delim that would apply.
         for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
             if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
                 && Some(self.token.span) > unmatched.unclosed_span
@@ -1038,7 +1048,7 @@
                 let unmatched = self.unclosed_delims.remove(pos);
                 let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
 
-                 // We want to suggest the inclusion of the closing delimiter where it makes
+                // We want to suggest the inclusion of the closing delimiter where it makes
                 // the most sense, which is immediately after the last token:
                 //
                 //  {foo(bar {}}
@@ -1064,7 +1074,7 @@
         }
     }
 
-    /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid.
+    /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid.
     crate fn eat_bad_pub(&mut self) {
         if self.token.is_keyword(kw::Pub) {
             match self.parse_visibility(false) {
@@ -1079,21 +1089,21 @@
         }
     }
 
-    // Eat tokens until we can be relatively sure we reached the end of the
-    // statement. This is something of a best-effort heuristic.
-    //
-    // We terminate when we find an unmatched `}` (without consuming it).
+    /// Eats tokens until we can be relatively sure we reached the end of the
+    /// statement. This is something of a best-effort heuristic.
+    ///
+    /// We terminate when we find an unmatched `}` (without consuming it).
     crate fn recover_stmt(&mut self) {
         self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore)
     }
 
-    // If `break_on_semi` is `Break`, then we will stop consuming tokens after
-    // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
-    // approximate - it can mean we break too early due to macros, but that
-    // should only lead to sub-optimal recovery, not inaccurate parsing).
-    //
-    // If `break_on_block` is `Break`, then we will stop consuming tokens
-    // after finding (and consuming) a brace-delimited block.
+    /// If `break_on_semi` is `Break`, then we will stop consuming tokens after
+    /// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
+    /// approximate -- it can mean we break too early due to macros, but that
+    /// should only lead to sub-optimal recovery, not inaccurate parsing).
+    ///
+    /// If `break_on_block` is `Break`, then we will stop consuming tokens
+    /// after finding (and consuming) a brace-delimited block.
     crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) {
         let mut brace_depth = 0;
         let mut bracket_depth = 0;
diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs
index 652ae95..c1ec419 100644
--- a/src/libsyntax/parse/lexer/tests.rs
+++ b/src/libsyntax/parse/lexer/tests.rs
@@ -4,9 +4,10 @@
 use crate::source_map::{SourceMap, FilePathMapping};
 use crate::parse::token;
 use crate::with_default_globals;
+
+use errors::{Handler, emitter::EmitterWriter};
 use std::io;
 use std::path::PathBuf;
-use errors::{Handler, emitter::EmitterWriter};
 use syntax_pos::{BytePos, Span};
 
 fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
@@ -21,7 +22,7 @@
     ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm)
 }
 
-// open a string reader for the given string
+// Creates a string reader for the given string.
 fn setup<'a>(sm: &SourceMap,
                 sess: &'a ParseSess,
                 teststr: String)
@@ -50,7 +51,7 @@
         assert_eq!(tok1.kind, tok2.kind);
         assert_eq!(tok1.span, tok2.span);
         assert_eq!(string_reader.next_token(), token::Whitespace);
-        // read another token:
+        // Read another token.
         let tok3 = string_reader.next_token();
         assert_eq!(string_reader.pos.clone(), BytePos(28));
         let tok4 = Token::new(
@@ -65,15 +66,15 @@
     })
 }
 
-// check that the given reader produces the desired stream
-// of tokens (stop checking after exhausting the expected vec)
+// Checks that the given reader produces the desired stream
+// of tokens (stop checking after exhausting `expected`).
 fn check_tokenization(mut string_reader: StringReader<'_>, expected: Vec<TokenKind>) {
     for expected_tok in &expected {
         assert_eq!(&string_reader.next_token(), expected_tok);
     }
 }
 
-// make the identifier by looking up the string in the interner
+// Makes the identifier by looking up the string in the interner.
 fn mk_ident(id: &str) -> TokenKind {
     token::Ident(Symbol::intern(id), false)
 }
@@ -201,7 +202,7 @@
                     setup(&sm, &sh, format!("{}suffix", $input)).next_token(),
                     mk_lit(token::$tok_type, $tok_contents, Some("suffix")),
                 );
-                // with a whitespace separator:
+                // with a whitespace separator
                 assert_eq!(
                     setup(&sm, &sh, format!("{} suffix", $input)).next_token(),
                     mk_lit(token::$tok_type, $tok_contents, None),
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index b1af480..2441a02 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -8,17 +8,18 @@
 use crate::parse::parser::emit_unclosed_delims;
 use crate::parse::token::TokenKind;
 use crate::tokenstream::{TokenStream, TokenTree};
-use crate::diagnostics::plugin::ErrorMap;
 use crate::print::pprust;
 use crate::symbol::Symbol;
 
 use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
+use rustc_data_structures::fx::{FxHashSet, FxHashMap};
+#[cfg(target_arch = "x86_64")]
+use rustc_data_structures::static_assert_size;
 use rustc_data_structures::sync::{Lrc, Lock, Once};
 use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
 use syntax_pos::edition::Edition;
 use syntax_pos::hygiene::ExpnId;
 
-use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use std::borrow::Cow;
 use std::path::{Path, PathBuf};
 use std::str;
@@ -39,6 +40,11 @@
 
 pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
 
+// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
+// (See also the comment on `DiagnosticBuilderInner`.)
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(PResult<'_, bool>, 16);
+
 /// Collected spans during parsing for places where a certain feature was
 /// used and should be feature gated accordingly in `check_crate`.
 #[derive(Default)]
@@ -64,8 +70,6 @@
     pub missing_fragment_specifiers: Lock<FxHashSet<Span>>,
     /// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
     pub raw_identifier_spans: Lock<Vec<Span>>,
-    /// The registered diagnostics codes.
-    crate registered_diagnostics: Lock<ErrorMap>,
     /// Used to determine and report recursive module inclusions.
     included_mod_stack: Lock<Vec<PathBuf>>,
     source_map: Lrc<SourceMap>,
@@ -81,25 +85,26 @@
 impl ParseSess {
     pub fn new(file_path_mapping: FilePathMapping) -> Self {
         let cm = Lrc::new(SourceMap::new(file_path_mapping));
-        let handler = Handler::with_tty_emitter(ColorConfig::Auto,
-                                                true,
-                                                None,
-                                                Some(cm.clone()));
+        let handler = Handler::with_tty_emitter(
+            ColorConfig::Auto,
+            true,
+            None,
+            Some(cm.clone()),
+        );
         ParseSess::with_span_handler(handler, cm)
     }
 
-    pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> ParseSess {
-        ParseSess {
+    pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self {
+        Self {
             span_diagnostic: handler,
             unstable_features: UnstableFeatures::from_environment(),
             config: FxHashSet::default(),
+            edition: ExpnId::root().expn_data().edition,
             missing_fragment_specifiers: Lock::new(FxHashSet::default()),
             raw_identifier_spans: Lock::new(Vec::new()),
-            registered_diagnostics: Lock::new(ErrorMap::new()),
             included_mod_stack: Lock::new(vec![]),
             source_map,
             buffered_lints: Lock::new(vec![]),
-            edition: ExpnId::root().expn_data().edition,
             ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
             injected_crate_name: Once::new(),
             gated_spans: GatedSpans::default(),
@@ -155,17 +160,17 @@
 #[derive(Copy, Clone)]
 pub enum DirectoryOwnership {
     Owned {
-        // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`
+        // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`.
         relative: Option<ast::Ident>,
     },
     UnownedViaBlock,
     UnownedViaMod(bool /* legacy warnings? */),
 }
 
-// a bunch of utility functions of the form parse_<thing>_from_<source>
+// A bunch of utility functions of the form `parse_<thing>_from_<source>`
 // where <thing> includes crate, expr, item, stmt, tts, and one that
 // uses a HOF to parse anything, and <source> includes file and
-// source_str.
+// `source_str`.
 
 pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
     let mut parser = new_parser_from_file(sess, input);
@@ -219,14 +224,13 @@
     Ok(parser)
 }
 
-/// Creates a new parser, handling errors as appropriate
-/// if the file doesn't exist
+/// Creates a new parser, handling errors as appropriate if the file doesn't exist.
 pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> {
     source_file_to_parser(sess, file_to_source_file(sess, path, None))
 }
 
-/// Creates a new parser, returning buffered diagnostics if the file doesn't
-/// exist or from lexing the initial token stream.
+/// Creates a new parser, returning buffered diagnostics if the file doesn't exist,
+/// or from lexing the initial token stream.
 pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path)
     -> Result<Parser<'a>, Vec<Diagnostic>> {
     let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?;
@@ -234,8 +238,8 @@
 }
 
 /// Given a session, a crate config, a path, and a span, add
-/// the file at the given path to the source_map, and return a parser.
-/// On an error, use the given span as the source of the problem.
+/// the file at the given path to the `source_map`, and returns a parser.
+/// On an error, uses the given span as the source of the problem.
 pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
                                     path: &Path,
                                     directory_ownership: DirectoryOwnership,
@@ -247,13 +251,13 @@
     p
 }
 
-/// Given a source_file and config, return a parser
+/// Given a `source_file` and config, returns a parser.
 fn source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Parser<'_> {
     panictry_buffer!(&sess.span_diagnostic,
                      maybe_source_file_to_parser(sess, source_file))
 }
 
-/// Given a source_file and config, return a parser. Returns any buffered errors from lexing the
+/// Given a `source_file` and config, return a parser. Returns any buffered errors from lexing the
 /// initial token stream.
 fn maybe_source_file_to_parser(
     sess: &ParseSess,
@@ -270,14 +274,14 @@
     Ok(parser)
 }
 
-// must preserve old name for now, because quote! from the *existing*
-// compiler expands into it
+// Must preserve old name for now, because `quote!` from the *existing*
+// compiler expands into it.
 pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec<TokenTree>) -> Parser<'_> {
     stream_to_parser(sess, tts.into_iter().collect(), crate::MACRO_ARGUMENTS)
 }
 
 
-// base abstractions
+// Base abstractions
 
 /// Given a session and a path and an optional span (for error reporting),
 /// add the path to the session's source_map and return the new source_file or
@@ -296,7 +300,7 @@
 }
 
 /// Given a session and a path and an optional span (for error reporting),
-/// add the path to the session's `source_map` and return the new `source_file`.
+/// adds the path to the session's `source_map` and returns the new `source_file`.
 fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
                    -> Lrc<SourceFile> {
     match try_file_to_source_file(sess, path, spanopt) {
@@ -308,7 +312,7 @@
     }
 }
 
-/// Given a source_file, produces a sequence of token trees.
+/// Given a `source_file`, produces a sequence of token trees.
 pub fn source_file_to_stream(
     sess: &ParseSess,
     source_file: Lrc<SourceFile>,
@@ -352,7 +356,7 @@
     }
 }
 
-/// Given stream and the `ParseSess`, produces a parser.
+/// Given a stream and the `ParseSess`, produces a parser.
 pub fn stream_to_parser<'a>(
     sess: &'a ParseSess,
     stream: TokenStream,
@@ -361,7 +365,7 @@
     Parser::new(sess, stream, None, true, false, subparser_name)
 }
 
-/// Given stream, the `ParseSess` and the base directory, produces a parser.
+/// Given a stream, the `ParseSess` and the base directory, produces a parser.
 ///
 /// Use this function when you are creating a parser from the token stream
 /// and also care about the current working directory of the parser (e.g.,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 49b0555..fcebfa2 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -10,22 +10,22 @@
 mod stmt;
 mod generics;
 
-use crate::ast::{self, AttrStyle, Attribute, Param, BindingMode, StrStyle, SelfKind};
-use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind};
-use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar};
-use crate::source_map::{self, respan};
-use crate::parse::{SeqSep, literal, token};
+use crate::ast::{
+    self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, FnDecl, Ident,
+    IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility,
+    VisibilityKind, Unsafety,
+};
+use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep, literal, token};
+use crate::parse::diagnostics::{Error, dummy_arg};
 use crate::parse::lexer::UnmatchedBrace;
 use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
 use crate::parse::token::{Token, TokenKind, DelimToken};
-use crate::parse::{ParseSess, Directory, DirectoryOwnership};
 use crate::print::pprust;
 use crate::ptr::P;
-use crate::parse::PResult;
-use crate::ThinVec;
-use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
+use crate::source_map::{self, respan};
 use crate::symbol::{kw, sym, Symbol};
-use crate::parse::diagnostics::{Error, dummy_arg};
+use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
+use crate::ThinVec;
 
 use errors::{Applicability, DiagnosticId, FatalError};
 use rustc_target::spec::abi::{self, Abi};
@@ -56,7 +56,7 @@
     Ignore,
 }
 
-/// As maybe_whole_expr, but for things other than expressions
+/// Like `maybe_whole_expr`, but for things other than expressions.
 #[macro_export]
 macro_rules! maybe_whole {
     ($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
@@ -116,11 +116,11 @@
     /// with non-interpolated identifier and lifetime tokens they refer to.
     /// Perhaps the normalized / non-normalized setup can be simplified somehow.
     pub token: Token,
-    /// Span of the current non-normalized token.
+    /// The span of the current non-normalized token.
     meta_var_span: Option<Span>,
-    /// Span of the previous non-normalized token.
+    /// The span of the previous non-normalized token.
     pub prev_span: Span,
-    /// Kind of the previous normalized token (in simplified form).
+    /// The kind of the previous normalized token (in simplified form).
     prev_token_kind: PrevTokenKind,
     restrictions: Restrictions,
     /// Used to determine the path to externally loaded source files.
@@ -132,7 +132,7 @@
     /// into modules, and sub-parsers have new values for this name.
     pub root_module_name: Option<String>,
     crate expected_tokens: Vec<TokenType>,
-    crate token_cursor: TokenCursor,
+    token_cursor: TokenCursor,
     desugar_doc_comments: bool,
     /// `true` we should configure out of line modules as we parse.
     pub cfg_mods: bool,
@@ -143,7 +143,7 @@
     /// See the comments in the `parse_path_segment` function for more details.
     crate unmatched_angle_bracket_count: u32,
     crate max_angle_bracket_count: u32,
-    /// List of all unclosed delimiters found by the lexer. If an entry is used for error recovery
+    /// A list of all unclosed delimiters found by the lexer. If an entry is used for error recovery
     /// it gets removed from here. Every entry left at the end gets emitted as an independent
     /// error.
     crate unclosed_delims: Vec<UnmatchedBrace>,
@@ -161,19 +161,19 @@
 }
 
 #[derive(Clone)]
-crate struct TokenCursor {
-    crate frame: TokenCursorFrame,
-    crate stack: Vec<TokenCursorFrame>,
+struct TokenCursor {
+    frame: TokenCursorFrame,
+    stack: Vec<TokenCursorFrame>,
 }
 
 #[derive(Clone)]
-crate struct TokenCursorFrame {
-    crate delim: token::DelimToken,
-    crate span: DelimSpan,
-    crate open_delim: bool,
-    crate tree_cursor: tokenstream::Cursor,
-    crate close_delim: bool,
-    crate last_token: LastToken,
+struct TokenCursorFrame {
+    delim: token::DelimToken,
+    span: DelimSpan,
+    open_delim: bool,
+    tree_cursor: tokenstream::Cursor,
+    close_delim: bool,
+    last_token: LastToken,
 }
 
 /// This is used in `TokenCursorFrame` above to track tokens that are consumed
@@ -799,14 +799,14 @@
                             break;
                         }
                         Err(mut e) => {
-                            // Attempt to keep parsing if it was a similar separator
+                            // Attempt to keep parsing if it was a similar separator.
                             if let Some(ref tokens) = t.similar_tokens() {
                                 if tokens.contains(&self.token.kind) {
                                     self.bump();
                                 }
                             }
                             e.emit();
-                            // Attempt to keep parsing if it was an omitted separator
+                            // Attempt to keep parsing if it was an omitted separator.
                             match f(self) {
                                 Ok(t) => {
                                     v.push(t);
@@ -871,7 +871,7 @@
         self.parse_delim_comma_seq(token::Paren, f)
     }
 
-    /// Advance the parser by one token
+    /// Advance the parser by one token.
     pub fn bump(&mut self) {
         if self.prev_token_kind == PrevTokenKind::Eof {
             // Bumping after EOF is a bad sign, usually an infinite loop.
@@ -894,17 +894,17 @@
 
         self.token = self.next_tok();
         self.expected_tokens.clear();
-        // check after each token
+        // Check after each token.
         self.process_potential_macro_variable();
     }
 
-    /// Advance the parser using provided token as a next one. Use this when
+    /// Advances the parser using provided token as a next one. Use this when
     /// consuming a part of a token. For example a single `<` from `<<`.
     fn bump_with(&mut self, next: TokenKind, span: Span) {
         self.prev_span = self.token.span.with_hi(span.lo());
         // It would be incorrect to record the kind of the current token, but
         // fortunately for tokens currently using `bump_with`, the
-        // prev_token_kind will be of no use anyway.
+        // `prev_token_kind` will be of no use anyway.
         self.prev_token_kind = PrevTokenKind::Other;
         self.token = Token::new(next, span);
         self.expected_tokens.clear();
@@ -937,8 +937,8 @@
     fn parse_asyncness(&mut self) -> IsAsync {
         if self.eat_keyword(kw::Async) {
             IsAsync::Async {
-                closure_id: ast::DUMMY_NODE_ID,
-                return_impl_trait_id: ast::DUMMY_NODE_ID,
+                closure_id: DUMMY_NODE_ID,
+                return_impl_trait_id: DUMMY_NODE_ID,
             }
         } else {
             IsAsync::NotAsync
@@ -1040,7 +1040,14 @@
 
         let span = lo.to(self.token.span);
 
-        Ok(Param { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty })
+        Ok(Param {
+            attrs: attrs.into(),
+            id: ast::DUMMY_NODE_ID,
+            is_placeholder: false,
+            pat,
+            span,
+            ty,
+        })
     }
 
     /// Parses mutability (`mut` or nothing).
@@ -1497,7 +1504,7 @@
                         format!("in {}", path),
                         Applicability::MachineApplicable,
                     )
-                    .emit();  // emit diagnostic, but continue with public visibility
+                    .emit(); // Emit diagnostic, but continue with public visibility.
             }
         }
 
diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs
index 5b9f0f1..31b2844 100644
--- a/src/libsyntax/parse/parser/expr.rs
+++ b/src/libsyntax/parse/parser/expr.rs
@@ -1,26 +1,26 @@
-use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle};
-use super::{BlockMode, SemiColonMode};
-use super::{SeqSep, TokenExpectType};
+use super::{
+    Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode, SemiColonMode,
+    SeqSep, TokenExpectType,
+};
 use super::pat::{GateOr, PARAM_EXPECTED};
 
+use crate::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,
+};
 use crate::maybe_recover_from_interpolated_ty_qpath;
-use crate::ptr::P;
-use crate::ast::{self, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode};
-use crate::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm};
-use crate::ast::{Ty, TyKind, FunctionRetTy, Param, FnDecl};
-use crate::ast::{BinOpKind, BinOp, UnOp};
-use crate::ast::{Mac, AnonConst, Field};
-
 use crate::parse::classify;
 use crate::parse::token::{self, Token};
-use crate::parse::diagnostics::{Error};
+use crate::parse::diagnostics::Error;
 use crate::print::pprust;
+use crate::ptr::P;
 use crate::source_map::{self, Span};
 use crate::symbol::{kw, sym};
 use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
 
-use std::mem;
 use errors::Applicability;
+use std::mem;
 use rustc_data_structures::thin_vec::ThinVec;
 
 /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
@@ -51,7 +51,7 @@
                         $p.token.span, ExprKind::Block(block, None), ThinVec::new()
                     ));
                 }
-                // N.B: `NtIdent(ident)` is normalized to `Ident` in `fn bump`.
+                // N.B., `NtIdent(ident)` is normalized to `Ident` in `fn bump`.
                 _ => {},
             };
         }
@@ -231,7 +231,7 @@
 
             self.bump();
             if op.is_comparison() {
-                self.check_no_chained_comparison(&lhs, &op);
+                self.check_no_chained_comparison(&lhs, &op)?;
             }
             // Special cases:
             if op == AssocOp::As {
@@ -340,7 +340,7 @@
 
     fn is_at_start_of_range_notation_rhs(&self) -> bool {
         if self.token.can_begin_expr() {
-            // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
+            // Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
             if self.token == token::OpenDelim(token::Brace) {
                 return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
             }
@@ -350,12 +350,12 @@
         }
     }
 
-    /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr`
+    /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
     fn parse_prefix_range_expr(
         &mut self,
         already_parsed_attrs: Option<ThinVec<Attribute>>
     ) -> PResult<'a, P<Expr>> {
-        // Check for deprecated `...` syntax
+        // Check for deprecated `...` syntax.
         if self.token == token::DotDotDot {
             self.err_dotdotdot_syntax(self.token.span);
         }
@@ -389,7 +389,7 @@
         Ok(self.mk_expr(lo.to(hi), r, attrs))
     }
 
-    /// Parse a prefix-unary-operator expr
+    /// Parses a prefix-unary-operator expr.
     fn parse_prefix_expr(
         &mut self,
         already_parsed_attrs: Option<ThinVec<Attribute>>
@@ -549,7 +549,7 @@
                         let expr = mk_expr(self, P(Ty {
                             span: path.span,
                             node: TyKind::Path(None, path),
-                            id: ast::DUMMY_NODE_ID
+                            id: DUMMY_NODE_ID,
                         }));
 
                         let expr_str = self.span_to_snippet(expr.span)
@@ -565,7 +565,7 @@
                                 expr.span,
                                 &format!("try {} the cast value", op_verb),
                                 format!("({})", expr_str),
-                                Applicability::MachineApplicable
+                                Applicability::MachineApplicable,
                             )
                             .emit();
 
@@ -741,7 +741,6 @@
         })
     }
 
-
     /// At the bottom (top?) of the precedence hierarchy,
     /// Parses things like parenthesized exprs, macros, `return`, etc.
     ///
@@ -755,7 +754,7 @@
         // added to the return value after the fact.
         //
         // Therefore, prevent sub-parser from parsing
-        // attributes by giving them a empty "already parsed" list.
+        // attributes by giving them a empty "already-parsed" list.
         let mut attrs = ThinVec::new();
 
         let lo = self.token.span;
@@ -778,7 +777,7 @@
             }
         }
 
-        // Note: when adding new syntax here, don't forget to adjust TokenKind::can_begin_expr().
+        // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
         match self.token.kind {
             // This match arm is a special-case of the `_` match arm below and
             // could be removed without changing functionality, but it's faster
@@ -791,8 +790,8 @@
 
                 attrs.extend(self.parse_inner_attributes()?);
 
-                // (e) is parenthesized e
-                // (e,) is a tuple with only one field, e
+                // `(e)` is parenthesized `e`.
+                // `(e,)` is a tuple with only one field, `e`.
                 let mut es = vec![];
                 let mut trailing_comma = false;
                 let mut recovered = false;
@@ -800,7 +799,7 @@
                     es.push(match self.parse_expr() {
                         Ok(es) => es,
                         Err(mut err) => {
-                            // recover from parse error in tuple list
+                            // Recover from parse error in tuple list.
                             match self.token.kind {
                                 token::Ident(name, false)
                                 if name == kw::Underscore && self.look_ahead(1, |t| {
@@ -844,7 +843,7 @@
                 return self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs);
             }
             token::BinOp(token::Or) | token::OrOr => {
-                return self.parse_lambda_expr(attrs);
+                return self.parse_closure_expr(attrs);
             }
             token::OpenDelim(token::Bracket) => {
                 self.bump();
@@ -852,21 +851,21 @@
                 attrs.extend(self.parse_inner_attributes()?);
 
                 if self.eat(&token::CloseDelim(token::Bracket)) {
-                    // Empty vector.
+                    // Empty vector
                     ex = ExprKind::Array(Vec::new());
                 } else {
-                    // Nonempty vector.
+                    // Non-empty vector
                     let first_expr = self.parse_expr()?;
                     if self.eat(&token::Semi) {
-                        // Repeating array syntax: [ 0; 512 ]
+                        // Repeating array syntax: `[ 0; 512 ]`
                         let count = AnonConst {
-                            id: ast::DUMMY_NODE_ID,
+                            id: DUMMY_NODE_ID,
                             value: self.parse_expr()?,
                         };
                         self.expect(&token::CloseDelim(token::Bracket))?;
                         ex = ExprKind::Repeat(first_expr, count);
                     } else if self.eat(&token::Comma) {
-                        // Vector with two or more elements.
+                        // Vector with two or more elements
                         let remaining_exprs = self.parse_seq_to_end(
                             &token::CloseDelim(token::Bracket),
                             SeqSep::trailing_allowed(token::Comma),
@@ -876,7 +875,7 @@
                         exprs.extend(remaining_exprs);
                         ex = ExprKind::Array(exprs);
                     } else {
-                        // Vector with one element.
+                        // Vector with one element
                         self.expect(&token::CloseDelim(token::Bracket))?;
                         ex = ExprKind::Array(vec![first_expr]);
                     }
@@ -889,8 +888,38 @@
                     hi = path.span;
                     return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs));
                 }
+                if self.token.is_path_start() {
+                    let path = self.parse_path(PathStyle::Expr)?;
+
+                    // `!`, as an operator, is prefix, so we know this isn't that.
+                    if self.eat(&token::Not) {
+                        // MACRO INVOCATION expression
+                        let (delim, tts) = self.expect_delimited_token_tree()?;
+                        hi = self.prev_span;
+                        ex = ExprKind::Mac(Mac {
+                            path,
+                            tts,
+                            delim,
+                            span: lo.to(hi),
+                            prior_type_ascription: self.last_type_ascription,
+                        });
+                    } else if self.check(&token::OpenDelim(token::Brace)) {
+                        if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
+                            return expr;
+                        } else {
+                            hi = path.span;
+                            ex = ExprKind::Path(None, path);
+                        }
+                    } else {
+                        hi = path.span;
+                        ex = ExprKind::Path(None, path);
+                    }
+
+                    let expr = self.mk_expr(lo.to(hi), ex, attrs);
+                    return self.maybe_recover_from_bad_qpath(expr, true);
+                }
                 if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
-                    return self.parse_lambda_expr(attrs);
+                    return self.parse_closure_expr(attrs);
                 }
                 if self.eat_keyword(kw::If) {
                     return self.parse_if_expr(attrs);
@@ -952,7 +981,7 @@
                 }
                 if self.is_do_catch_block() {
                     let mut db = self.fatal("found removed `do catch` syntax");
-                    db.help("Following RFC #2388, the new non-placeholder syntax is `try`");
+                    db.help("following RFC #2388, the new non-placeholder syntax is `try`");
                     return Err(db);
                 }
                 if self.is_try_block() {
@@ -961,13 +990,13 @@
                     return self.parse_try_block(lo, attrs);
                 }
 
-                // Span::rust_2018() is somewhat expensive; don't get it repeatedly.
+                // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
                 let is_span_rust_2018 = self.token.span.rust_2018();
                 if is_span_rust_2018 && self.check_keyword(kw::Async) {
-                    return if self.is_async_block() { // check for `async {` and `async move {`
+                    return if self.is_async_block() { // Check for `async {` and `async move {`.
                         self.parse_async_block(attrs)
                     } else {
-                        self.parse_lambda_expr(attrs)
+                        self.parse_closure_expr(attrs)
                     };
                 }
                 if self.eat_keyword(kw::Return) {
@@ -1007,45 +1036,18 @@
                     let (await_hi, e_kind) = self.parse_incorrect_await_syntax(lo, self.prev_span)?;
                     hi = await_hi;
                     ex = e_kind;
-                } else if self.token.is_path_start() {
-                    let path = self.parse_path(PathStyle::Expr)?;
-
-                    // `!`, as an operator, is prefix, so we know this isn't that
-                    if self.eat(&token::Not) {
-                        // MACRO INVOCATION expression
-                        let (delim, tts) = self.expect_delimited_token_tree()?;
-                        hi = self.prev_span;
-                        ex = ExprKind::Mac(Mac {
-                            path,
-                            tts,
-                            delim,
-                            span: lo.to(hi),
-                            prior_type_ascription: self.last_type_ascription,
-                        });
-                    } else if self.check(&token::OpenDelim(token::Brace)) {
-                        if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
-                            return expr;
-                        } else {
-                            hi = path.span;
-                            ex = ExprKind::Path(None, path);
-                        }
-                    } else {
-                        hi = path.span;
-                        ex = ExprKind::Path(None, path);
-                    }
                 } else {
                     if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
                         // Don't complain about bare semicolons after unclosed braces
                         // recovery in order to keep the error count down. Fixing the
                         // delimiters will possibly also fix the bare semicolon found in
                         // expression context. For example, silence the following error:
-                        // ```
-                        // error: expected expression, found `;`
-                        //  --> file.rs:2:13
-                        //   |
-                        // 2 |     foo(bar(;
-                        //   |             ^ expected expression
-                        // ```
+                        //
+                        //     error: expected expression, found `;`
+                        //      --> file.rs:2:13
+                        //       |
+                        //     2 |     foo(bar(;
+                        //       |             ^ expected expression
                         self.bump();
                         return Ok(self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()));
                     }
@@ -1092,11 +1094,11 @@
         attrs.extend(self.parse_inner_attributes()?);
 
         let blk = self.parse_block_tail(lo, blk_mode)?;
-        return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs));
+        Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
     }
 
-    /// Parses `move |args| expr`.
-    fn parse_lambda_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+    /// Parses a closure expression (e.g., `move |args| expr`).
+    fn parse_closure_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         let lo = self.token.span;
 
         let movability = if self.eat_keyword(kw::Static) {
@@ -1111,7 +1113,7 @@
             IsAsync::NotAsync
         };
         if asyncness.is_async() {
-            // Feature gate `async ||` closures.
+            // Feature-gate `async ||` closures.
             self.sess.gated_spans.async_closure.borrow_mut().push(self.prev_span);
         }
 
@@ -1124,8 +1126,7 @@
                 self.parse_expr_res(restrictions, None)?
             },
             _ => {
-                // If an explicit return type is given, require a
-                // block to appear (RFC 968).
+                // If an explicit return type is given, require a block to appear (RFC 968).
                 let body_lo = self.token.span;
                 self.parse_block_expr(None, body_lo, BlockCheckMode::Default, ThinVec::new())?
             }
@@ -1137,7 +1138,7 @@
             attrs))
     }
 
-    /// Parse an optional `move` prefix to a closure lke construct.
+    /// Parses an optional `move` prefix to a closure lke construct.
     fn parse_capture_clause(&mut self) -> CaptureBy {
         if self.eat_keyword(kw::Move) {
             CaptureBy::Value
@@ -1172,7 +1173,7 @@
         }))
     }
 
-    /// Parses a parameter in a lambda header (e.g., `|arg, arg|`).
+    /// Parses a parameter in a closure header (e.g., `|arg, arg|`).
     fn parse_fn_block_param(&mut self) -> PResult<'a, Param> {
         let lo = self.token.span;
         let attrs = self.parse_param_attributes()?;
@@ -1181,7 +1182,7 @@
             self.parse_ty()?
         } else {
             P(Ty {
-                id: ast::DUMMY_NODE_ID,
+                id: DUMMY_NODE_ID,
                 node: TyKind::Infer,
                 span: self.prev_span,
             })
@@ -1192,7 +1193,8 @@
             ty: t,
             pat,
             span,
-            id: ast::DUMMY_NODE_ID
+            id: DUMMY_NODE_ID,
+            is_placeholder: false,
         })
     }
 
@@ -1229,7 +1231,7 @@
         Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs))
     }
 
-    /// Parse the condition of a `if`- or `while`-expression
+    /// Parses the condition of a `if` or `while` expression.
     fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
         let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
 
@@ -1246,8 +1248,7 @@
     /// The `let` token has already been eaten.
     fn parse_let_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         let lo = self.prev_span;
-        // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead.
-        let pat = self.parse_top_pat_unpack(GateOr::No)?;
+        let pat = self.parse_top_pat(GateOr::No)?;
         self.expect(&token::Eq)?;
         let expr = self.with_res(
             Restrictions::NO_STRUCT_LITERAL,
@@ -1258,7 +1259,7 @@
         Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs))
     }
 
-    /// `else` token already eaten
+    /// Parses an `else { ... }` expression (`else` token already eaten).
     fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
         if self.eat_keyword(kw::If) {
             return self.parse_if_expr(ThinVec::new());
@@ -1268,7 +1269,7 @@
         }
     }
 
-    /// Parse a 'for' .. 'in' expression ('for' token already eaten)
+    /// Parses a `for ... in` expression (`for` token already eaten).
     fn parse_for_expr(
         &mut self,
         opt_label: Option<Label>,
@@ -1324,7 +1325,7 @@
         Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
     }
 
-    /// Parse `loop {...}`, `loop` token already eaten.
+    /// Parses `loop { ... }` (`loop` token already eaten).
     fn parse_loop_expr(
         &mut self,
         opt_label: Option<Label>,
@@ -1347,7 +1348,7 @@
         }
     }
 
-    // `match` token already eaten
+    /// Parses a `match ... { ... }` expression (`match` token already eaten).
     fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         let match_span = self.prev_span;
         let lo = self.prev_span;
@@ -1389,8 +1390,7 @@
     crate fn parse_arm(&mut self) -> PResult<'a, Arm> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
-        // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead.
-        let pat = self.parse_top_pat_unpack(GateOr::No)?;
+        let pat = self.parse_top_pat(GateOr::No)?;
         let guard = if self.eat_keyword(kw::If) {
             Some(self.parse_expr()?)
         } else {
@@ -1451,11 +1451,12 @@
 
         Ok(ast::Arm {
             attrs,
-            pats: pat, // FIXME(or_patterns, Centril | dlrobertson): this should just be `pat,`.
+            pat,
             guard,
             body: expr,
             span: lo.to(hi),
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
+            is_placeholder: false,
         })
     }
 
@@ -1489,7 +1490,7 @@
         self.token.is_keyword(kw::Try) &&
         self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
         self.token.span.rust_2018() &&
-        // prevent `while try {} {}`, `if try {} {} else {}`, etc.
+        // Prevent `while try {} {}`, `if try {} {} else {}`, etc.
         !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
     }
 
@@ -1502,7 +1503,7 @@
         attrs.extend(iattrs);
         Ok(self.mk_expr(
             span_lo.to(body.span),
-            ExprKind::Async(capture_clause, ast::DUMMY_NODE_ID, body), attrs))
+            ExprKind::Async(capture_clause, DUMMY_NODE_ID, body), attrs))
     }
 
     fn is_async_block(&self) -> bool {
@@ -1525,18 +1526,18 @@
     ) -> Option<PResult<'a, P<Expr>>> {
         let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
         let certainly_not_a_block = || self.look_ahead(1, |t| t.is_ident()) && (
-            // `{ ident, ` cannot start a block
+            // `{ ident, ` cannot start a block.
             self.look_ahead(2, |t| t == &token::Comma) ||
             self.look_ahead(2, |t| t == &token::Colon) && (
-                // `{ ident: token, ` cannot start a block
+                // `{ ident: token, ` cannot start a block.
                 self.look_ahead(4, |t| t == &token::Comma) ||
-                // `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`
+                // `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`.
                 self.look_ahead(3, |t| !t.can_begin_type())
             )
         );
 
         if struct_allowed || certainly_not_a_block() {
-            // This is a struct literal, but we don't can't accept them here
+            // This is a struct literal, but we don't can't accept them here.
             let expr = self.parse_struct_expr(lo, path.clone(), attrs.clone());
             if let (Ok(expr), false) = (&expr, struct_allowed) {
                 self.struct_span_err(
@@ -1604,14 +1605,15 @@
             let mut recovery_field = None;
             if let token::Ident(name, _) = self.token.kind {
                 if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
-                    // Use in case of error after field-looking code: `S { foo: () with a }`
+                    // Use in case of error after field-looking code: `S { foo: () with a }`.
                     recovery_field = Some(ast::Field {
                         ident: Ident::new(name, self.token.span),
                         span: self.token.span,
                         expr: self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()),
                         is_shorthand: false,
                         attrs: ThinVec::new(),
-                        id: ast::DUMMY_NODE_ID,
+                        id: DUMMY_NODE_ID,
+                        is_placeholder: false,
                     });
                 }
             }
@@ -1637,7 +1639,7 @@
             match self.expect_one_of(&[token::Comma],
                                      &[token::CloseDelim(token::Brace)]) {
                 Ok(_) => if let Some(f) = parsed_field.or(recovery_field) {
-                    // only include the field if there's no parse error for the field name
+                    // Only include the field if there's no parse error for the field name.
                     fields.push(f);
                 }
                 Err(mut e) => {
@@ -1657,7 +1659,7 @@
         return Ok(self.mk_expr(span, ExprKind::Struct(pth, fields, base), attrs));
     }
 
-    /// Parse ident (COLON expr)?
+    /// Parses `ident (COLON expr)?`.
     fn parse_field(&mut self) -> PResult<'a, Field> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
@@ -1697,7 +1699,8 @@
             expr,
             is_shorthand,
             attrs: attrs.into(),
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
+            is_placeholder: false,
         })
     }
 
@@ -1770,6 +1773,6 @@
     }
 
     crate fn mk_expr(&self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> {
-        P(Expr { node, span, attrs, id: ast::DUMMY_NODE_ID })
+        P(Expr { node, span, attrs, id: DUMMY_NODE_ID })
     }
 }
diff --git a/src/libsyntax/parse/parser/generics.rs b/src/libsyntax/parse/parser/generics.rs
index 54f24f8..3e6118a 100644
--- a/src/libsyntax/parse/parser/generics.rs
+++ b/src/libsyntax/parse/parser/generics.rs
@@ -49,7 +49,8 @@
             bounds,
             kind: GenericParamKind::Type {
                 default,
-            }
+            },
+            is_placeholder: false
         })
     }
 
@@ -66,7 +67,8 @@
             bounds: Vec::new(),
             kind: GenericParamKind::Const {
                 ty,
-            }
+            },
+            is_placeholder: false
         })
     }
 
@@ -90,6 +92,7 @@
                     attrs: attrs.into(),
                     bounds,
                     kind: ast::GenericParamKind::Lifetime,
+                    is_placeholder: false
                 });
             } else if self.check_keyword(kw::Const) {
                 // Parse const parameter.
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index 59a3ade..cf19664 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -2,34 +2,36 @@
 
 use crate::maybe_whole;
 use crate::ptr::P;
-use crate::ast::{self, Ident, Attribute, AttrStyle};
-use crate::ast::{Item, ItemKind, ImplItem, TraitItem, TraitItemKind};
-use crate::ast::{UseTree, UseTreeKind, PathSegment};
-use crate::ast::{IsAuto, Constness, IsAsync, Unsafety, Defaultness};
-use crate::ast::{Visibility, VisibilityKind, Mutability, FnDecl, FnHeader};
-use crate::ast::{ForeignItem, ForeignItemKind};
-use crate::ast::{Ty, TyKind, GenericBounds, TraitRef};
-use crate::ast::{EnumDef, VariantData, StructField, AnonConst};
-use crate::ast::{Mac, MacDelimiter};
+use crate::ast::{
+    self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle,
+    Item, ItemKind, ImplItem, TraitItem, TraitItemKind,
+    UseTree, UseTreeKind, PathSegment,
+    IsAuto, Constness, IsAsync, Unsafety, Defaultness,
+    Visibility, VisibilityKind, Mutability, FnDecl, FnHeader,
+    ForeignItem, ForeignItemKind,
+    Ty, TyKind, Generics, GenericBounds, TraitRef,
+    EnumDef, VariantData, StructField, AnonConst,
+    Mac, MacDelimiter,
+};
 use crate::ext::base::DummyResult;
 use crate::parse::token;
 use crate::parse::parser::maybe_append;
-use crate::parse::diagnostics::{Error};
+use crate::parse::diagnostics::Error;
 use crate::tokenstream::{TokenTree, TokenStream};
 use crate::source_map::{respan, Span, Spanned};
 use crate::symbol::{kw, sym};
 
 use std::mem;
 use log::debug;
-use rustc_target::spec::abi::{Abi};
+use rustc_target::spec::abi::Abi;
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 
-/// Whether the type alias or associated type is a concrete type or an opaque type
+/// Whether the type alias or associated type is a concrete type or an opaque type.
 #[derive(Debug)]
 pub enum AliasKind {
-    /// Just a new name for the same type
+    /// Just a new name for the same type.
     Weak(P<Ty>),
-    /// Only trait impls of the type will be usable, not the actual type itself
+    /// Only trait impls of the type will be usable, not the actual type itself.
     OpaqueTy(GenericBounds),
 }
 
@@ -200,7 +202,7 @@
             return Ok(Some(item));
         }
 
-        // Parse `async unsafe? fn`.
+        // Parses `async unsafe? fn`.
         if self.check_keyword(kw::Async) {
             let async_span = self.token.span;
             if self.is_keyword_ahead(1, &[kw::Fn])
@@ -214,8 +216,8 @@
                 let (ident, item_, extra_attrs) =
                     self.parse_item_fn(unsafety,
                                     respan(async_span, IsAsync::Async {
-                                        closure_id: ast::DUMMY_NODE_ID,
-                                        return_impl_trait_id: ast::DUMMY_NODE_ID,
+                                        closure_id: DUMMY_NODE_ID,
+                                        return_impl_trait_id: DUMMY_NODE_ID,
                                     }),
                                     respan(fn_span, Constness::NotConst),
                                     Abi::Rust)?;
@@ -286,7 +288,7 @@
             && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
             // UNSAFE FUNCTION ITEM
             self.bump(); // `unsafe`
-            // `{` is also expected after `unsafe`, in case of error, include it in the diagnostic
+            // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
             self.check(&token::OpenDelim(token::Brace));
             let abi = if self.eat_keyword(kw::Extern) {
                 self.parse_opt_abi()?.unwrap_or(Abi::C)
@@ -521,7 +523,7 @@
 
             let mac_lo = self.token.span;
 
-            // item macro.
+            // Item macro
             let path = self.parse_path(PathStyle::Mod)?;
             self.expect(&token::Not)?;
             let (delim, tts) = self.expect_delimited_token_tree()?;
@@ -659,7 +661,7 @@
         let mut generics = if self.choose_generics_over_qpath() {
             self.parse_generics()?
         } else {
-            ast::Generics::default()
+            Generics::default()
         };
 
         // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
@@ -676,7 +678,7 @@
                           self.look_ahead(1, |t| t != &token::Lt) {
             let span = self.prev_span.between(self.token.span);
             self.struct_span_err(span, "missing trait in a trait impl").emit();
-            P(Ty { node: TyKind::Path(None, err_path(span)), span, id: ast::DUMMY_NODE_ID })
+            P(Ty { node: TyKind::Path(None, err_path(span)), span, id: DUMMY_NODE_ID })
         } else {
             self.parse_ty()?
         };
@@ -798,7 +800,7 @@
             self.expect(&token::Eq)?;
             let expr = self.parse_expr()?;
             self.expect(&token::Semi)?;
-            (name, ast::ImplItemKind::Const(typ, expr), ast::Generics::default())
+            (name, ast::ImplItemKind::Const(typ, expr), Generics::default())
         } else {
             let (name, inner_attrs, generics, node) = self.parse_impl_method(&vis, at_end)?;
             attrs.extend(inner_attrs);
@@ -806,7 +808,7 @@
         };
 
         Ok(ImplItem {
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
             span: lo.to(self.prev_span),
             ident: name,
             vis,
@@ -847,14 +849,13 @@
             !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
     }
 
-    /// Parse a method or a macro invocation in a trait impl.
+    /// Parses a method or a macro invocation in a trait impl.
     fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
-                         -> PResult<'a, (Ident, Vec<Attribute>, ast::Generics,
-                             ast::ImplItemKind)> {
-        // code copied from parse_macro_use_or_failure... abstraction!
+                         -> PResult<'a, (Ident, Vec<Attribute>, Generics, ast::ImplItemKind)> {
+        // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
         if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
             // method macro
-            Ok((Ident::invalid(), vec![], ast::Generics::default(),
+            Ok((Ident::invalid(), vec![], Generics::default(),
                 ast::ImplItemKind::Macro(mac)))
         } else {
             let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
@@ -930,7 +931,7 @@
         };
 
         if self.eat(&token::Eq) {
-            // it's a trait alias
+            // It's a trait alias.
             let bounds = self.parse_generic_bounds(None)?;
             tps.where_clause = self.parse_where_clause()?;
             self.expect(&token::Semi)?;
@@ -948,7 +949,7 @@
             }
             Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
         } else {
-            // it's a normal trait
+            // It's a normal trait.
             tps.where_clause = self.parse_where_clause()?;
             self.expect(&token::OpenDelim(token::Brace))?;
             let mut trait_items = vec![];
@@ -1023,10 +1024,10 @@
                 self.expect(&token::Semi)?;
                 None
             };
-            (ident, TraitItemKind::Const(ty, default), ast::Generics::default())
+            (ident, TraitItemKind::Const(ty, default), Generics::default())
         } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
             // trait item macro.
-            (Ident::invalid(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
+            (Ident::invalid(), ast::TraitItemKind::Macro(mac), Generics::default())
         } else {
             let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
 
@@ -1089,7 +1090,7 @@
         };
 
         Ok(TraitItem {
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
             ident: name,
             attrs,
             generics,
@@ -1103,7 +1104,7 @@
     ///
     ///     TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
     fn parse_trait_item_assoc_ty(&mut self)
-        -> PResult<'a, (Ident, TraitItemKind, ast::Generics)> {
+        -> PResult<'a, (Ident, TraitItemKind, Generics)> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -1165,7 +1166,7 @@
                     UseTreeKind::Nested(self.parse_use_tree_list()?)
                 }
             } else {
-                UseTreeKind::Simple(self.parse_rename()?, ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID)
+                UseTreeKind::Simple(self.parse_rename()?, DUMMY_NODE_ID, DUMMY_NODE_ID)
             }
         };
 
@@ -1178,7 +1179,7 @@
     /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
     /// ```
     fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
-        self.parse_delim_comma_seq(token::Brace, |p| Ok((p.parse_use_tree()?, ast::DUMMY_NODE_ID)))
+        self.parse_delim_comma_seq(token::Brace, |p| Ok((p.parse_use_tree()?, DUMMY_NODE_ID)))
             .map(|(r, _)| r)
     }
 
@@ -1240,9 +1241,9 @@
         let mut idents = vec![];
         let mut replacement = vec![];
         let mut fixed_crate_name = false;
-        // Accept `extern crate name-like-this` for better diagnostics
+        // Accept `extern crate name-like-this` for better diagnostics.
         let dash = token::BinOp(token::BinOpToken::Minus);
-        if self.token == dash {  // Do not include `-` as part of the expected tokens list
+        if self.token == dash {  // Do not include `-` as part of the expected tokens list.
             while self.eat(&dash) {
                 fixed_crate_name = true;
                 replacement.push((self.prev_span, "_".to_string()));
@@ -1255,7 +1256,7 @@
             for part in idents {
                 fixed_name.push_str(&format!("_{}", part.name));
             }
-            ident = Ident::from_str(&fixed_name).with_span_pos(fixed_name_sp);
+            ident = Ident::from_str_and_span(&fixed_name, fixed_name_sp);
 
             self.struct_span_err(fixed_name_sp, error_msg)
                 .span_label(fixed_name_sp, "dash-separated idents are not valid")
@@ -1283,7 +1284,7 @@
     }
 
     /// Parses the name and optional generic types of a function header.
-    fn parse_fn_header(&mut self) -> PResult<'a, (Ident, ast::Generics)> {
+    fn parse_fn_header(&mut self) -> PResult<'a, (Ident, Generics)> {
         let id = self.parse_ident()?;
         let generics = self.parse_generics()?;
         Ok((id, generics))
@@ -1379,7 +1380,7 @@
                     ForeignItem {
                         ident: Ident::invalid(),
                         span: lo.to(self.prev_span),
-                        id: ast::DUMMY_NODE_ID,
+                        id: DUMMY_NODE_ID,
                         attrs,
                         vis: visibility,
                         node: ForeignItemKind::Macro(mac),
@@ -1415,7 +1416,7 @@
             ident,
             attrs,
             node: ForeignItemKind::Fn(decl, generics),
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
             span: lo.to(hi),
             vis,
         })
@@ -1435,7 +1436,7 @@
             ident,
             attrs,
             node: ForeignItemKind::Static(ty, mutbl),
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
             span: lo.to(hi),
             vis,
         })
@@ -1453,7 +1454,7 @@
             ident,
             attrs,
             node: ForeignItemKind::Ty,
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
             span: lo.to(hi),
             vis
         })
@@ -1461,7 +1462,7 @@
 
     fn is_static_global(&mut self) -> bool {
         if self.check_keyword(kw::Static) {
-            // Check if this could be a closure
+            // Check if this could be a closure.
             !self.look_ahead(1, |token| {
                 if token.is_keyword(kw::Move) {
                     return true;
@@ -1492,7 +1493,7 @@
 
     /// Parses `type Foo = Bar;` or returns `None`
     /// without modifying the parser state.
-    fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> {
+    fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, Generics)>> {
         // This parses the grammar:
         //     Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
         if self.eat_keyword(kw::Type) {
@@ -1503,7 +1504,7 @@
     }
 
     /// Parses a type alias or opaque type.
-    fn parse_type_alias(&mut self) -> PResult<'a, (Ident, AliasKind, ast::Generics)> {
+    fn parse_type_alias(&mut self) -> PResult<'a, (Ident, AliasKind, Generics)> {
         let ident = self.parse_ident()?;
         let mut tps = self.parse_generics()?;
         tps.where_clause = self.parse_where_clause()?;
@@ -1536,7 +1537,7 @@
     }
 
     /// Parses the part of an enum declaration following the `{`.
-    fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
+    fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> {
         let mut variants = Vec::new();
         while self.token != token::CloseDelim(token::Brace) {
             let variant_attrs = self.parse_outer_attributes()?;
@@ -1552,15 +1553,15 @@
             } else if self.check(&token::OpenDelim(token::Paren)) {
                 VariantData::Tuple(
                     self.parse_tuple_struct_body()?,
-                    ast::DUMMY_NODE_ID,
+                    DUMMY_NODE_ID,
                 )
             } else {
-                VariantData::Unit(ast::DUMMY_NODE_ID)
+                VariantData::Unit(DUMMY_NODE_ID)
             };
 
             let disr_expr = if self.eat(&token::Eq) {
                 Some(AnonConst {
-                    id: ast::DUMMY_NODE_ID,
+                    id: DUMMY_NODE_ID,
                     value: self.parse_expr()?,
                 })
             } else {
@@ -1569,11 +1570,12 @@
 
             let vr = ast::Variant {
                 ident,
-                id: ast::DUMMY_NODE_ID,
+                id: DUMMY_NODE_ID,
                 attrs: variant_attrs,
                 data: struct_def,
                 disr_expr,
                 span: vlo.to(self.prev_span),
+                is_placeholder: false,
             };
             variants.push(vr);
 
@@ -1622,7 +1624,7 @@
             generics.where_clause = self.parse_where_clause()?;
             if self.eat(&token::Semi) {
                 // If we see a: `struct Foo<T> where T: Copy;` style decl.
-                VariantData::Unit(ast::DUMMY_NODE_ID)
+                VariantData::Unit(DUMMY_NODE_ID)
             } else {
                 // If we see: `struct Foo<T> where T: Copy { ... }`
                 let (fields, recovered) = self.parse_record_struct_body()?;
@@ -1630,14 +1632,14 @@
             }
         // No `where` so: `struct Foo<T>;`
         } else if self.eat(&token::Semi) {
-            VariantData::Unit(ast::DUMMY_NODE_ID)
+            VariantData::Unit(DUMMY_NODE_ID)
         // Record-style struct definition
         } else if self.token == token::OpenDelim(token::Brace) {
             let (fields, recovered) = self.parse_record_struct_body()?;
             VariantData::Struct(fields, recovered)
         // Tuple-style struct definition with optional where-clause.
         } else if self.token == token::OpenDelim(token::Paren) {
-            let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID);
+            let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
             generics.where_clause = self.parse_where_clause()?;
             self.expect(&token::Semi)?;
             body
@@ -1726,9 +1728,10 @@
                 span: lo.to(ty.span),
                 vis,
                 ident: None,
-                id: ast::DUMMY_NODE_ID,
+                id: DUMMY_NODE_ID,
                 ty,
                 attrs,
+                is_placeholder: false,
             })
         }).map(|(r, _)| r)
     }
@@ -1817,9 +1820,10 @@
             span: lo.to(self.prev_span),
             ident: Some(name),
             vis,
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
             ty,
             attrs,
+            is_placeholder: false,
         })
     }
 
@@ -1909,7 +1913,7 @@
         P(Item {
             ident,
             attrs,
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
             node,
             vis,
             span,
diff --git a/src/libsyntax/parse/parser/module.rs b/src/libsyntax/parse/parser/module.rs
index 3f6f87b..2d2fb48 100644
--- a/src/libsyntax/parse/parser/module.rs
+++ b/src/libsyntax/parse/parser/module.rs
@@ -36,12 +36,12 @@
         krate
     }
 
-    /// Parse a `mod <foo> { ... }` or `mod <foo>;` item
+    /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
     pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> {
         let (in_cfg, outer_attrs) = {
             let mut strip_unconfigured = crate::config::StripUnconfigured {
                 sess: self.sess,
-                features: None, // don't perform gated feature checking
+                features: None, // Don't perform gated feature checking.
             };
             let mut outer_attrs = outer_attrs.to_owned();
             strip_unconfigured.process_cfg_attrs(&mut outer_attrs);
@@ -57,7 +57,7 @@
                     self.submod_path(id, &outer_attrs, id_span)?;
                 let (module, mut attrs) =
                     self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
-                // Record that we fetched the mod from an external file
+                // Record that we fetched the mod from an external file.
                 if warn {
                     let attr = attr::mk_attr_outer(
                         attr::mk_word_item(Ident::with_dummy_span(sym::warn_directory_ownership)));
diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs
index 823f880..08ee3a6 100644
--- a/src/libsyntax/parse/parser/pat.rs
+++ b/src/libsyntax/parse/parser/pat.rs
@@ -36,16 +36,6 @@
         self.parse_pat_with_range_pat(true, expected)
     }
 
-    // FIXME(or_patterns, Centril | dlrobertson):
-    // remove this and use `parse_top_pat` everywhere it is used instead.
-    pub(super) fn parse_top_pat_unpack(&mut self, gate_or: GateOr) -> PResult<'a, Vec<P<Pat>>> {
-        self.parse_top_pat(gate_or)
-            .map(|pat| pat.and_then(|pat| match pat.node {
-                PatKind::Or(pats) => pats,
-                node => vec![self.mk_pat(pat.span, node)],
-            }))
-    }
-
     /// Entry point to the main pattern parser.
     /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level.
     pub(super) fn parse_top_pat(&mut self, gate_or: GateOr) -> PResult<'a, P<Pat>> {
@@ -854,14 +844,14 @@
         // Check if a colon exists one ahead. This means we're parsing a fieldname.
         let hi;
         let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
-            // Parsing a pattern of the form "fieldname: pat"
+            // Parsing a pattern of the form `fieldname: pat`.
             let fieldname = self.parse_field_name()?;
             self.bump();
             let pat = self.parse_pat_with_or_inner()?;
             hi = pat.span;
             (pat, fieldname, false)
         } else {
-            // Parsing a pattern of the form "(box) (ref) (mut) fieldname"
+            // Parsing a pattern of the form `(box) (ref) (mut) fieldname`.
             let is_box = self.eat_keyword(kw::Box);
             let boxed_span = self.token.span;
             let is_ref = self.eat_keyword(kw::Ref);
@@ -892,6 +882,7 @@
             attrs: attrs.into(),
             id: ast::DUMMY_NODE_ID,
             span: lo.to(hi),
+            is_placeholder: false,
         })
     }
 
diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs
index 651ebf6..04bd61a 100644
--- a/src/libsyntax/parse/parser/stmt.rs
+++ b/src/libsyntax/parse/parser/stmt.rs
@@ -5,12 +5,12 @@
 
 use crate::ptr::P;
 use crate::{maybe_whole, ThinVec};
-use crate::ast::{self, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind};
+use crate::ast::{self, DUMMY_NODE_ID, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind};
 use crate::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter};
 use crate::ext::base::DummyResult;
 use crate::parse::{classify, DirectoryOwnership};
 use crate::parse::diagnostics::Error;
-use crate::parse::token::{self};
+use crate::parse::token;
 use crate::source_map::{respan, Span};
 use crate::symbol::{kw, sym};
 
@@ -18,7 +18,7 @@
 use errors::Applicability;
 
 impl<'a> Parser<'a> {
-    /// Parse a statement. This stops just before trailing semicolons on everything but items.
+    /// Parses a statement. This stops just before trailing semicolons on everything but items.
     /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
     pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> {
         Ok(self.parse_stmt_(true))
@@ -43,7 +43,7 @@
 
         Ok(Some(if self.eat_keyword(kw::Let) {
             Stmt {
-                id: ast::DUMMY_NODE_ID,
+                id: DUMMY_NODE_ID,
                 node: StmtKind::Local(self.parse_local(attrs.into())?),
                 span: lo.to(self.prev_span),
             }
@@ -53,7 +53,7 @@
             lo,
         )? {
             Stmt {
-                id: ast::DUMMY_NODE_ID,
+                id: DUMMY_NODE_ID,
                 node: StmtKind::Item(macro_def),
                 span: lo.to(self.prev_span),
             }
@@ -85,7 +85,7 @@
                 })?;
 
                 return Ok(Some(Stmt {
-                    id: ast::DUMMY_NODE_ID,
+                    id: DUMMY_NODE_ID,
                     node: StmtKind::Expr(expr),
                     span: lo.to(self.prev_span),
                 }));
@@ -114,17 +114,17 @@
             // We used to incorrectly stop parsing macro-expanded statements here.
             // If the next token will be an error anyway but could have parsed with the
             // earlier behavior, stop parsing here and emit a warning to avoid breakage.
-            else if macro_legacy_warnings &&
-                    self.token.can_begin_expr() &&
-                    match self.token.kind {
-                // These can continue an expression, so we can't stop parsing and warn.
-                token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
-                token::BinOp(token::Minus) | token::BinOp(token::Star) |
-                token::BinOp(token::And) | token::BinOp(token::Or) |
-                token::AndAnd | token::OrOr |
-                token::DotDot | token::DotDotDot | token::DotDotEq => false,
-                _ => true,
-            } {
+            else if macro_legacy_warnings && self.token.can_begin_expr() &&
+                match self.token.kind {
+                    // These can continue an expression, so we can't stop parsing and warn.
+                    token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
+                    token::BinOp(token::Minus) | token::BinOp(token::Star) |
+                    token::BinOp(token::And) | token::BinOp(token::Or) |
+                    token::AndAnd | token::OrOr |
+                    token::DotDot | token::DotDotDot | token::DotDotEq => false,
+                    _ => true,
+                }
+            {
                 self.warn_missing_semicolon();
                 StmtKind::Mac(P((mac, style, attrs.into())))
             } else {
@@ -135,7 +135,7 @@
                 StmtKind::Expr(e)
             };
             Stmt {
-                id: ast::DUMMY_NODE_ID,
+                id: DUMMY_NODE_ID,
                 span: lo.to(hi),
                 node,
             }
@@ -148,7 +148,7 @@
 
             match item {
                 Some(i) => Stmt {
-                    id: ast::DUMMY_NODE_ID,
+                    id: DUMMY_NODE_ID,
                     span: lo.to(i.span),
                     node: StmtKind::Item(i),
                 },
@@ -178,7 +178,7 @@
                         // an empty tuple that spans the excess semicolons
                         // to preserve this info until the lint stage
                         return Ok(Some(Stmt {
-                            id: ast::DUMMY_NODE_ID,
+                            id: DUMMY_NODE_ID,
                             span: lo.to(last_semi),
                             node: StmtKind::Semi(self.mk_expr(lo.to(last_semi),
                                 ExprKind::Tup(Vec::new()),
@@ -196,7 +196,7 @@
                     let e = self.parse_expr_res(
                         Restrictions::STMT_EXPR, Some(attrs.into()))?;
                     Stmt {
-                        id: ast::DUMMY_NODE_ID,
+                        id: DUMMY_NODE_ID,
                         span: lo.to(e.span),
                         node: StmtKind::Expr(e),
                     }
@@ -218,7 +218,7 @@
             match self.parse_ty() {
                 Ok(ty) => (None, Some(ty)),
                 Err(mut err) => {
-                    // Rewind to before attempting to parse the type and continue parsing
+                    // Rewind to before attempting to parse the type and continue parsing.
                     let parser_snapshot_after_type = self.clone();
                     mem::replace(self, parser_snapshot_before_type);
 
@@ -272,7 +272,7 @@
             ty,
             pat,
             init,
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
             span: lo.to(hi),
             attrs,
         }))
@@ -334,18 +334,18 @@
             //    if (cond)
             //      bar;
             //
-            // Which is valid in other languages, but not Rust.
+            // which is valid in other languages, but not Rust.
             match self.parse_stmt_without_recovery(false) {
                 Ok(Some(stmt)) => {
                     if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
                         || do_not_suggest_help {
-                        // if the next token is an open brace (e.g., `if a b {`), the place-
-                        // inside-a-block suggestion would be more likely wrong than right
+                        // If the next token is an open brace (e.g., `if a b {`), the place-
+                        // inside-a-block suggestion would be more likely wrong than right.
                         e.span_label(sp, "expected `{`");
                         return Err(e);
                     }
                     let mut stmt_span = stmt.span;
-                    // expand the span to include the semicolon, if it exists
+                    // Expand the span to include the semicolon, if it exists.
                     if self.eat(&token::Semi) {
                         stmt_span = stmt_span.with_hi(self.prev_span.hi());
                     }
@@ -354,7 +354,7 @@
                             stmt_span,
                             "try placing this code inside a block",
                             format!("{{ {} }}", snippet),
-                            // speculative, has been misleading in the past (#46836)
+                            // Speculative; has been misleading in the past (#46836).
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -399,7 +399,7 @@
                     err.emit();
                     self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
                     Some(Stmt {
-                        id: ast::DUMMY_NODE_ID,
+                        id: DUMMY_NODE_ID,
                         node: StmtKind::Expr(DummyResult::raw_expr(self.token.span, true)),
                         span: self.token.span,
                     })
@@ -415,7 +415,7 @@
         }
         Ok(P(ast::Block {
             stmts,
-            id: ast::DUMMY_NODE_ID,
+            id: DUMMY_NODE_ID,
             rules: s,
             span: lo.to(self.prev_span),
         }))
@@ -423,7 +423,7 @@
 
     /// Parses a statement, including the trailing semicolon.
     crate fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option<Stmt>> {
-        // skip looking for a trailing semicolon when we have an interpolated statement
+        // Skip looking for a trailing semicolon when we have an interpolated statement.
         maybe_whole!(self, NtStmt, |x| Some(x));
 
         let mut stmt = match self.parse_stmt_without_recovery(macro_legacy_warnings)? {
@@ -469,7 +469,7 @@
         self.diagnostic().struct_span_warn(self.token.span, {
             &format!("expected `;`, found {}", self.this_token_descr())
         }).note({
-            "This was erroneously allowed and will become a hard error in a future release"
+            "this was erroneously allowed and will become a hard error in a future release"
         }).emit();
     }
 }
diff --git a/src/libsyntax/parse/tests.rs b/src/libsyntax/parse/tests.rs
index 6a789ef..5cb59b3 100644
--- a/src/libsyntax/parse/tests.rs
+++ b/src/libsyntax/parse/tests.rs
@@ -25,12 +25,12 @@
     new_parser_from_source_str(sess, name, source).parse_item()
 }
 
-// produce a syntax_pos::span
+// Produces a `syntax_pos::span`.
 fn sp(a: u32, b: u32) -> Span {
     Span::with_root_ctxt(BytePos(a), BytePos(b))
 }
 
-/// Parse a string, return an expr
+/// Parses a string, return an expression.
 fn string_to_expr(source_str : String) -> P<ast::Expr> {
     let ps = ParseSess::new(FilePathMapping::empty());
     with_error_checking_parse(source_str, &ps, |p| {
@@ -38,7 +38,7 @@
     })
 }
 
-/// Parse a string, return an item
+/// Parses a string, returns an item.
 fn string_to_item(source_str : String) -> Option<P<ast::Item>> {
     let ps = ParseSess::new(FilePathMapping::empty());
     with_error_checking_parse(source_str, &ps, |p| {
@@ -53,7 +53,7 @@
     })
 }
 
-// check the token-tree-ization of macros
+// Checks the token-tree-ization of macros.
 #[test]
 fn string_to_tts_macro () {
     with_default_globals(|| {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index bead941..bf36c0d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -35,6 +35,7 @@
     SubItem(ast::NodeId),
     Expr(&'a ast::Expr),
     Pat(&'a ast::Pat),
+    Crate(&'a ast::Crate),
 }
 
 pub trait PpAnn {
@@ -119,23 +120,28 @@
     if is_expanded && sess.injected_crate_name.try_get().is_some() {
         // We need to print `#![no_std]` (and its feature gate) so that
         // compiling pretty-printed source won't inject libstd again.
-        // However we don't want these attributes in the AST because
+        // However, we don't want these attributes in the AST because
         // of the feature gate, so we fake them up here.
 
-        // #![feature(prelude_import)]
+        // `#![feature(prelude_import)]`
         let pi_nested = attr::mk_nested_word_item(ast::Ident::with_dummy_span(sym::prelude_import));
         let list = attr::mk_list_item(ast::Ident::with_dummy_span(sym::feature), vec![pi_nested]);
         let fake_attr = attr::mk_attr_inner(list);
         s.print_attribute(&fake_attr);
 
-        // #![no_std]
-        let no_std_meta = attr::mk_word_item(ast::Ident::with_dummy_span(sym::no_std));
-        let fake_attr = attr::mk_attr_inner(no_std_meta);
-        s.print_attribute(&fake_attr);
+        // Currently, in Rust 2018 we don't have `extern crate std;` at the crate
+        // root, so this is not needed, and actually breaks things.
+        if sess.edition == syntax_pos::edition::Edition::Edition2015 {
+            // `#![no_std]`
+            let no_std_meta = attr::mk_word_item(ast::Ident::with_dummy_span(sym::no_std));
+            let fake_attr = attr::mk_attr_inner(no_std_meta);
+            s.print_attribute(&fake_attr);
+        }
     }
 
     s.print_mod(&krate.module, &krate.attrs);
     s.print_remaining_comments();
+    s.ann.post(&mut s, AnnNode::Crate(krate));
     s.s.eof()
 }
 
@@ -356,11 +362,7 @@
     to_string(|s| s.print_tt(tt, false))
 }
 
-pub fn tts_to_string(tts: &[tokenstream::TokenTree]) -> String {
-    tokens_to_string(tts.iter().cloned().collect())
-}
-
-pub fn tokens_to_string(tokens: TokenStream) -> String {
+pub fn tts_to_string(tokens: TokenStream) -> String {
     to_string(|s| s.print_tts(tokens, false))
 }
 
@@ -398,9 +400,9 @@
 
 fn block_to_string(blk: &ast::Block) -> String {
     to_string(|s| {
-        // containing cbox, will be closed by print-block at }
+        // Containing cbox, will be closed by `print_block` at `}`.
         s.cbox(INDENT_UNIT);
-        // head-ibox, will be closed by print-block after {
+        // Head-ibox, will be closed by `print_block` after `{`.
         s.ibox(0);
         s.print_block(blk)
     })
@@ -443,7 +445,7 @@
     }
 }
 
-pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefMut {
+pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut {
     fn comments(&mut self) -> &mut Option<Comments<'a>>;
     fn print_ident(&mut self, ident: ast::Ident);
     fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
@@ -495,7 +497,7 @@
                 self.hardbreak_if_not_bol();
                 for line in &cmnt.lines {
                     // Don't print empty lines because they will end up as trailing
-                    // whitespace
+                    // whitespace.
                     if !line.is_empty() {
                         self.word(line.clone());
                     }
@@ -783,11 +785,11 @@
 
     fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
         let w = w.into();
-        // outer-box is consistent
+        // Outer-box is consistent.
         self.cbox(INDENT_UNIT);
-        // head-box is inconsistent
+        // Head-box is inconsistent.
         self.ibox(w.len() + 1);
-        // keyword that starts the head
+        // Keyword that starts the head.
         if !w.is_empty() {
             self.word_nbsp(w);
         }
@@ -795,7 +797,7 @@
 
     fn bopen(&mut self) {
         self.word("{");
-        self.end(); // close the head-box
+        self.end(); // Close the head-box.
     }
 
     fn bclose_maybe_open(&mut self, span: syntax_pos::Span, close_box: bool) {
@@ -803,7 +805,7 @@
         self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
         self.word("}");
         if close_box {
-            self.end(); // close the outer-box
+            self.end(); // Close the outer-box.
         }
     }
 
@@ -900,8 +902,6 @@
         self.s.word("*/")
     }
 
-
-
     crate fn commasep_cmnt<T, F, G>(&mut self,
                                   b: Breaks,
                                   elts: &[T],
@@ -928,12 +928,12 @@
     }
 
     crate fn commasep_exprs(&mut self, b: Breaks,
-                          exprs: &[P<ast::Expr>]) {
+                            exprs: &[P<ast::Expr>]) {
         self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
     }
 
     crate fn print_mod(&mut self, _mod: &ast::Mod,
-                     attrs: &[ast::Attribute]) {
+                       attrs: &[ast::Attribute]) {
         self.print_inner_attributes(attrs);
         for item in &_mod.items {
             self.print_item(item);
@@ -941,7 +941,7 @@
     }
 
     crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
-                             attrs: &[ast::Attribute]) {
+                               attrs: &[ast::Attribute]) {
         self.print_inner_attributes(attrs);
         for item in &nmod.items {
             self.print_foreign_item(item);
@@ -1136,7 +1136,7 @@
         self.s.word(";")
     }
 
-    /// Pretty-print an item
+    /// Pretty-prints an item.
     crate fn print_item(&mut self, item: &ast::Item) {
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(item.span.lo());
@@ -1371,8 +1371,12 @@
                 }
             }
             ast::ItemKind::MacroDef(ref macro_def) => {
-                let (kw, has_bang) =
-                    if macro_def.legacy { ("macro_rules", true) } else { ("macro", false) };
+                let (kw, has_bang) = if macro_def.legacy {
+                    ("macro_rules", true)
+                } else {
+                    self.print_visibility(&item.vis);
+                    ("macro", false)
+                };
                 self.print_mac_common(
                     Some(MacHeader::Keyword(kw)),
                     has_bang,
@@ -1489,7 +1493,7 @@
                     self.s.word(";");
                 }
                 self.end();
-                self.end(); // close the outer-box
+                self.end(); // Close the outer-box.
             }
             ast::VariantData::Struct(..) => {
                 self.print_where_clause(&generics.where_clause);
@@ -1714,11 +1718,11 @@
         self.ann.post(self, AnnNode::Block(blk))
     }
 
-    /// Print a `let pats = scrutinee` expression.
-    crate fn print_let(&mut self, pats: &[P<ast::Pat>], scrutinee: &ast::Expr) {
+    /// Print a `let pat = scrutinee` expression.
+    crate fn print_let(&mut self, pat: &ast::Pat, scrutinee: &ast::Expr) {
         self.s.word("let ");
 
-        self.print_pats(pats);
+        self.print_pat(pat);
         self.s.space();
 
         self.word_space("=");
@@ -1793,7 +1797,7 @@
         self.print_expr_cond_paren(expr, expr.precedence().order() < prec)
     }
 
-    /// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
+    /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
     /// `if cond { ... }`.
     crate fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
         self.print_expr_cond_paren(expr, Self::cond_needs_par(expr))
@@ -1812,7 +1816,7 @@
         }
     }
 
-    /// Print `expr` or `(expr)` when `needs_par` holds.
+    /// Prints `expr` or `(expr)` when `needs_par` holds.
     fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
         if needs_par {
             self.popen();
@@ -2044,8 +2048,8 @@
                 self.word_space(":");
                 self.print_type(ty);
             }
-            ast::ExprKind::Let(ref pats, ref scrutinee) => {
-                self.print_let(pats, scrutinee);
+            ast::ExprKind::Let(ref pat, ref scrutinee) => {
+                self.print_let(pat, scrutinee);
             }
             ast::ExprKind::If(ref test, ref blk, ref elseopt) => {
                 self.print_if(test, blk, elseopt.as_ref().map(|e| &**e));
@@ -2455,21 +2459,16 @@
         self.ann.post(self, AnnNode::Pat(pat))
     }
 
-    fn print_pats(&mut self, pats: &[P<ast::Pat>]) {
-        self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p));
-    }
-
     fn print_arm(&mut self, arm: &ast::Arm) {
-        // I have no idea why this check is necessary, but here it
-        // is :(
+        // Note, I have no idea why this check is necessary, but here it is.
         if arm.attrs.is_empty() {
             self.s.space();
         }
         self.cbox(INDENT_UNIT);
         self.ibox(0);
-        self.maybe_print_comment(arm.pats[0].span.lo());
+        self.maybe_print_comment(arm.pat.span.lo());
         self.print_outer_attributes(&arm.attrs);
-        self.print_pats(&arm.pats);
+        self.print_pat(&arm.pat);
         self.s.space();
         if let Some(ref e) = arm.guard {
             self.word_space("if");
@@ -2485,21 +2484,21 @@
                     self.word_space(":");
                 }
 
-                // the block will close the pattern's ibox
+                // The block will close the pattern's ibox.
                 self.print_block_unclosed_indent(blk);
 
-                // If it is a user-provided unsafe block, print a comma after it
+                // If it is a user-provided unsafe block, print a comma after it.
                 if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
                     self.s.word(",");
                 }
             }
             _ => {
-                self.end(); // close the ibox for the pattern
+                self.end(); // Close the ibox for the pattern.
                 self.print_expr(&arm.body);
                 self.s.word(",");
             }
         }
-        self.end(); // close enclosing cbox
+        self.end(); // Close enclosing cbox.
     }
 
     fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) {
diff --git a/src/libsyntax/print/pprust/tests.rs b/src/libsyntax/print/pprust/tests.rs
index 2521467..05d78cd 100644
--- a/src/libsyntax/print/pprust/tests.rs
+++ b/src/libsyntax/print/pprust/tests.rs
@@ -12,8 +12,8 @@
         s.head("");
         s.print_fn(decl, header, Some(name),
                    generics, &source_map::dummy_spanned(ast::VisibilityKind::Inherited));
-        s.end(); // Close the head box
-        s.end(); // Close the outer box
+        s.end(); // Close the head box.
+        s.end(); // Close the outer box.
     })
 }
 
@@ -58,10 +58,10 @@
             ident,
             attrs: Vec::new(),
             id: ast::DUMMY_NODE_ID,
-            // making this up as I go.... ?
             data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
             disr_expr: None,
             span: syntax_pos::DUMMY_SP,
+            is_placeholder: false,
         };
 
         let varstr = variant_to_string(&var);
diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs
index 7190cfd..d7ea799 100644
--- a/src/libsyntax/source_map.rs
+++ b/src/libsyntax/source_map.rs
@@ -1,10 +1,10 @@
-//! The SourceMap tracks all the source code used within a single crate, mapping
+//! The `SourceMap` tracks all the source code used within a single crate, mapping
 //! from integer byte positions to the original source code location. Each bit
 //! of source parsed during crate parsing (typically files, in-memory strings,
 //! or various bits of macro expansion) cover a continuous range of bytes in the
-//! SourceMap and are represented by SourceFiles. Byte positions are stored in
-//! `spans` and used pervasively in the compiler. They are absolute positions
-//! within the SourceMap, which upon request can be converted to line and column
+//! `SourceMap` and are represented by `SourceFile`s. Byte positions are stored in
+//! `Span`` and used pervasively in the compiler. They are absolute positions
+//! within the `SourceMap`, which upon request can be converted to line and column
 //! information, source code snippets, etc.
 
 pub use syntax_pos::*;
@@ -94,7 +94,7 @@
     }
 }
 
-// This is a SourceFile identifier that is used to correlate SourceFiles between
+// This is a `SourceFile` identifier that is used to correlate `SourceFile`s between
 // subsequent compilation sessions (which is something we need to do during
 // incremental compilation).
 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
@@ -103,8 +103,8 @@
 impl StableSourceFileId {
     pub fn new(source_file: &SourceFile) -> StableSourceFileId {
         StableSourceFileId::new_from_pieces(&source_file.name,
-                                         source_file.name_was_remapped,
-                                         source_file.unmapped_path.as_ref())
+                                            source_file.name_was_remapped,
+                                            source_file.unmapped_path.as_ref())
     }
 
     pub fn new_from_pieces(name: &FileName,
@@ -134,7 +134,7 @@
     files: Lock<SourceMapFiles>,
     file_loader: Box<dyn FileLoader + Sync + Send>,
     // This is used to apply the file path remapping as specified via
-    // --remap-path-prefix to all SourceFiles allocated within this SourceMap.
+    // `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`.
     path_mapping: FilePathMapping,
 }
 
@@ -204,14 +204,14 @@
         match self.files.borrow().source_files.last() {
             None => 0,
             // Add one so there is some space between files. This lets us distinguish
-            // positions in the source_map, even in the presence of zero-length files.
+            // positions in the `SourceMap`, even in the presence of zero-length files.
             Some(last) => last.end_pos.to_usize() + 1,
         }
     }
 
-    /// Creates a new source_file.
-    /// If a file already exists in the source_map with the same id, that file is returned
-    /// unmodified
+    /// Creates a new `SourceFile`.
+    /// If a file already exists in the `SourceMap` with the same ID, that file is returned
+    /// unmodified.
     pub fn new_source_file(&self, filename: FileName, src: String) -> Lrc<SourceFile> {
         self.try_new_source_file(filename, src)
             .unwrap_or_else(|OffsetOverflowError| {
@@ -268,8 +268,8 @@
         Ok(lrc_sf)
     }
 
-    /// Allocates a new SourceFile representing a source file from an external
-    /// crate. The source code of such an "imported source_file" is not available,
+    /// Allocates a new `SourceFile` representing a source file from an external
+    /// crate. The source code of such an "imported `SourceFile`" is not available,
     /// but we still know enough to generate accurate debuginfo location
     /// information for things inlined from other crates.
     pub fn new_imported_source_file(
@@ -334,7 +334,7 @@
                  pos.col.to_usize() + 1)
     }
 
-    // If there is a doctest_offset, apply it to the line
+    // If there is a doctest offset, applies it to the line.
     pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize {
         return match file {
             FileName::DocTest(_, offset) => {
@@ -348,7 +348,7 @@
         }
     }
 
-    /// Lookup source information about a BytePos
+    /// Looks up source information about a `BytePos`.
     pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
         let chpos = self.bytepos_to_file_charpos(pos);
         match self.lookup_line(pos) {
@@ -411,7 +411,7 @@
         }
     }
 
-    // If the relevant source_file is empty, we don't return a line number.
+    // If the corresponding `SourceFile` is empty, does not return a line number.
     pub fn lookup_line(&self, pos: BytePos) -> Result<SourceFileAndLine, Lrc<SourceFile>> {
         let idx = self.lookup_source_file_idx(pos);
 
@@ -423,15 +423,15 @@
         }
     }
 
-    /// Returns `Some(span)`, a union of the lhs and rhs span. The lhs must precede the rhs. If
-    /// there are gaps between lhs and rhs, the resulting union will cross these gaps.
-    /// For this to work, the spans have to be:
+    /// Returns `Some(span)`, a union of the LHS and RHS span. The LHS must precede the RHS. If
+    /// there are gaps between LHS and RHS, the resulting union will cross these gaps.
+    /// For this to work,
     ///
-    ///    * the ctxt of both spans much match
-    ///    * the lhs span needs to end on the same line the rhs span begins
-    ///    * the lhs span must start at or before the rhs span
+    ///    * the syntax contexts of both spans much match,
+    ///    * the LHS span needs to end on the same line the RHS span begins,
+    ///    * the LHS span must start at or before the RHS span.
     pub fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span> {
-        // make sure we're at the same expansion id
+        // Ensure we're at the same expansion ID.
         if sp_lhs.ctxt() != sp_rhs.ctxt() {
             return None;
         }
@@ -445,12 +445,12 @@
             Err(_) => return None
         };
 
-        // if we must cross lines to merge, don't merge
+        // If we must cross lines to merge, don't merge.
         if lhs_end.line != rhs_begin.line {
             return None;
         }
 
-        // ensure these follow the expected order and we don't overlap
+        // Ensure these follow the expected order and that we don't overlap.
         if (sp_lhs.lo() <= sp_rhs.lo()) && (sp_lhs.hi() <= sp_rhs.lo()) {
             Some(sp_lhs.to(sp_rhs))
         } else {
@@ -466,11 +466,12 @@
         let lo = self.lookup_char_pos(sp.lo());
         let hi = self.lookup_char_pos(sp.hi());
         format!("{}:{}:{}: {}:{}",
-                        lo.file.name,
-                        lo.line,
-                        lo.col.to_usize() + 1,
-                        hi.line,
-                        hi.col.to_usize() + 1)
+            lo.file.name,
+            lo.line,
+            lo.col.to_usize() + 1,
+            hi.line,
+            hi.col.to_usize() + 1,
+        )
     }
 
     pub fn span_to_filename(&self, sp: Span) -> FileName {
@@ -479,7 +480,7 @@
 
     pub fn span_to_unmapped_path(&self, sp: Span) -> FileName {
         self.lookup_char_pos(sp.lo()).file.unmapped_path.clone()
-            .expect("SourceMap::span_to_unmapped_path called for imported SourceFile?")
+            .expect("`SourceMap::span_to_unmapped_path` called for imported `SourceFile`?")
     }
 
     pub fn is_multiline(&self, sp: Span) -> bool {
@@ -586,7 +587,7 @@
         }
     }
 
-    /// Returns the source snippet as `String` corresponding to the given `Span`
+    /// Returns the source snippet as `String` corresponding to the given `Span`.
     pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
         self.span_to_source(sp, |src, start_index, end_index| src.get(start_index..end_index)
             .map(|s| s.to_string())
@@ -602,14 +603,14 @@
         }
     }
 
-    /// Returns the source snippet as `String` before the given `Span`
+    /// Returns the source snippet as `String` before the given `Span`.
     pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
         self.span_to_source(sp, |src, start_index, _| src.get(..start_index)
             .map(|s| s.to_string())
             .ok_or_else(|| SpanSnippetError::IllFormedSpan(sp)))
     }
 
-    /// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span
+    /// Extends the given `Span` to just after the previous occurrence of `c`. Return the same span
     /// if no character could be found or if an error occurred while retrieving the code snippet.
     pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span {
         if let Ok(prev_source) = self.span_to_prev_source(sp) {
@@ -622,8 +623,8 @@
         sp
     }
 
-    /// Extend the given `Span` to just after the previous occurrence of `pat` when surrounded by
-    /// whitespace. Return the same span if no character could be found or if an error occurred
+    /// Extends the given `Span` to just after the previous occurrence of `pat` when surrounded by
+    /// whitespace. Returns the same span if no character could be found or if an error occurred
     /// while retrieving the code snippet.
     pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str, accept_newlines: bool) -> Span {
         // assure that the pattern is delimited, to avoid the following
@@ -643,7 +644,8 @@
         sp
     }
 
-    /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char`
+    /// Given a `Span`, tries to get a shorter span ending before the first occurrence of `char`
+    /// ``c`.
     pub fn span_until_char(&self, sp: Span, c: char) -> Span {
         match self.span_to_snippet(sp) {
             Ok(snippet) => {
@@ -658,7 +660,7 @@
         }
     }
 
-    /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char`
+    /// Given a `Span`, tries to get a shorter span ending just after the first occurrence of `char`
     /// `c`.
     pub fn span_through_char(&self, sp: Span, c: char) -> Span {
         if let Ok(snippet) = self.span_to_snippet(sp) {
@@ -669,8 +671,8 @@
         sp
     }
 
-    /// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or
-    /// the original `Span`.
+    /// Given a `Span`, gets a new `Span` covering the first token and all its trailing whitespace
+    /// or the original `Span`.
     ///
     /// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned.
     pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
@@ -689,15 +691,15 @@
         })
     }
 
-    /// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or
-    /// the original `Span` in case of error.
+    /// Given a `Span`, gets a new `Span` covering the first token without its trailing whitespace
+    /// or the original `Span` in case of error.
     ///
     /// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned.
     pub fn span_until_whitespace(&self, sp: Span) -> Span {
         self.span_take_while(sp, |c| !c.is_whitespace())
     }
 
-    /// Given a `Span`, get a shorter one until `predicate` yields false.
+    /// Given a `Span`, gets a shorter one until `predicate` yields `false`.
     pub fn span_take_while<P>(&self, sp: Span, predicate: P) -> Span
         where P: for <'r> FnMut(&'r char) -> bool
     {
@@ -717,7 +719,7 @@
         self.span_until_char(sp, '{')
     }
 
-    /// Returns a new span representing just the start-point of this span
+    /// Returns a new span representing just the start point of this span.
     pub fn start_point(&self, sp: Span) -> Span {
         let pos = sp.lo().0;
         let width = self.find_width_of_character_at_span(sp, false);
@@ -726,7 +728,7 @@
         sp.with_hi(end_point)
     }
 
-    /// Returns a new span representing just the end-point of this span
+    /// Returns a new span representing just the end point of this span.
     pub fn end_point(&self, sp: Span) -> Span {
         let pos = sp.hi().0;
 
@@ -737,7 +739,7 @@
         sp.with_lo(end_point)
     }
 
-    /// Returns a new span representing the next character after the end-point of this span
+    /// Returns a new span representing the next character after the end-point of this span.
     pub fn next_point(&self, sp: Span) -> Span {
         let start_of_next_point = sp.hi().0;
 
@@ -840,7 +842,7 @@
         None
     }
 
-    /// For a global BytePos compute the local offset within the containing SourceFile
+    /// For a global `BytePos`, computes the local offset within the containing `SourceFile`.
     pub fn lookup_byte_offset(&self, bpos: BytePos) -> SourceFileAndBytePos {
         let idx = self.lookup_source_file_idx(bpos);
         let sf = (*self.files.borrow().source_files)[idx].clone();
@@ -848,22 +850,22 @@
         SourceFileAndBytePos {sf, pos: offset}
     }
 
-    /// Converts an absolute BytePos to a CharPos relative to the source_file.
+    /// Converts an absolute `BytePos` to a `CharPos` relative to the `SourceFile`.
     pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
         let idx = self.lookup_source_file_idx(bpos);
         let map = &(*self.files.borrow().source_files)[idx];
 
-        // The number of extra bytes due to multibyte chars in the SourceFile
+        // The number of extra bytes due to multibyte chars in the `SourceFile`.
         let mut total_extra_bytes = 0;
 
         for mbc in map.multibyte_chars.iter() {
             debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
             if mbc.pos < bpos {
-                // every character is at least one byte, so we only
+                // Every character is at least one byte, so we only
                 // count the actual extra bytes.
                 total_extra_bytes += mbc.bytes as u32 - 1;
                 // We should never see a byte position in the middle of a
-                // character
+                // character.
                 assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
             } else {
                 break;
@@ -874,13 +876,13 @@
         CharPos(bpos.to_usize() - map.start_pos.to_usize() - total_extra_bytes as usize)
     }
 
-    // Return the index of the source_file (in self.files) which contains pos.
+    // Returns the index of the `SourceFile` (in `self.files`) that contains `pos`.
     pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize {
         let files = self.files.borrow();
         let files = &files.source_files;
         let count = files.len();
 
-        // Binary search for the source_file.
+        // Binary search for the `SourceFile`.
         let mut a = 0;
         let mut b = count;
         while b - a > 1 {
@@ -911,8 +913,8 @@
         }).ok()
     }
 
-    /// Take the span of a type parameter in a function signature and try to generate a span for the
-    /// function name (with generics) and a new snippet for this span with the pointed type
+    /// Takes the span of a type parameter in a function signature and try to generate a span for
+    /// the function name (with generics) and a new snippet for this span with the pointed type
     /// parameter as a new local type parameter.
     ///
     /// For instance:
@@ -928,18 +930,18 @@
     ///
     /// Attention: The method used is very fragile since it essentially duplicates the work of the
     /// parser. If you need to use this function or something similar, please consider updating the
-    /// source_map functions and this function to something more robust.
+    /// `SourceMap` functions and this function to something more robust.
     pub fn generate_local_type_param_snippet(&self, span: Span) -> Option<(Span, String)> {
         // Try to extend the span to the previous "fn" keyword to retrieve the function
-        // signature
+        // signature.
         let sugg_span = self.span_extend_to_prev_str(span, "fn", false);
         if sugg_span != span {
             if let Ok(snippet) = self.span_to_snippet(sugg_span) {
-                // Consume the function name
+                // Consume the function name.
                 let mut offset = snippet.find(|c: char| !c.is_alphanumeric() && c != '_')
                     .expect("no label after fn");
 
-                // Consume the generics part of the function signature
+                // Consume the generics part of the function signature.
                 let mut bracket_counter = 0;
                 let mut last_char = None;
                 for c in snippet[offset..].chars() {
@@ -953,11 +955,11 @@
                     last_char = Some(c);
                 }
 
-                // Adjust the suggestion span to encompass the function name with its generics
+                // Adjust the suggestion span to encompass the function name with its generics.
                 let sugg_span = sugg_span.with_hi(BytePos(sugg_span.lo().0 + offset as u32));
 
                 // Prepare the new suggested snippet to append the type parameter that triggered
-                // the error in the generics of the function signature
+                // the error in the generics of the function signature.
                 let mut new_snippet = if last_char == Some('>') {
                     format!("{}, ", &snippet[..(offset - '>'.len_utf8())])
                 } else {
diff --git a/src/libsyntax/source_map/tests.rs b/src/libsyntax/source_map/tests.rs
index c7b8332..1525433 100644
--- a/src/libsyntax/source_map/tests.rs
+++ b/src/libsyntax/source_map/tests.rs
@@ -4,18 +4,24 @@
 
 fn init_source_map() -> SourceMap {
     let sm = SourceMap::new(FilePathMapping::empty());
-    sm.new_source_file(PathBuf::from("blork.rs").into(),
-                    "first line.\nsecond line".to_string());
-    sm.new_source_file(PathBuf::from("empty.rs").into(),
-                    String::new());
-    sm.new_source_file(PathBuf::from("blork2.rs").into(),
-                    "first line.\nsecond line".to_string());
+    sm.new_source_file(
+        PathBuf::from("blork.rs").into(),
+        "first line.\nsecond line".to_string(),
+    );
+    sm.new_source_file(
+        PathBuf::from("empty.rs").into(),
+        String::new(),
+    );
+    sm.new_source_file(
+        PathBuf::from("blork2.rs").into(),
+        "first line.\nsecond line".to_string(),
+    );
     sm
 }
 
+/// Tests `lookup_byte_offset`.
 #[test]
 fn t3() {
-    // Test lookup_byte_offset
     let sm = init_source_map();
 
     let srcfbp1 = sm.lookup_byte_offset(BytePos(23));
@@ -31,9 +37,9 @@
     assert_eq!(srcfbp2.pos, BytePos(0));
 }
 
+/// Tests `bytepos_to_file_charpos`.
 #[test]
 fn t4() {
-    // Test bytepos_to_file_charpos
     let sm = init_source_map();
 
     let cp1 = sm.bytepos_to_file_charpos(BytePos(22));
@@ -43,9 +49,9 @@
     assert_eq!(cp2, CharPos(0));
 }
 
+/// Tests zero-length `SourceFile`s.
 #[test]
 fn t5() {
-    // Test zero-length source_files.
     let sm = init_source_map();
 
     let loc1 = sm.lookup_char_pos(BytePos(22));
@@ -61,7 +67,7 @@
 
 fn init_source_map_mbc() -> SourceMap {
     let sm = SourceMap::new(FilePathMapping::empty());
-    // € is a three byte utf8 char.
+    // "€" is a three-byte UTF8 char.
     sm.new_source_file(PathBuf::from("blork.rs").into(),
                     "fir€st €€€€ line.\nsecond line".to_string());
     sm.new_source_file(PathBuf::from("blork2.rs").into(),
@@ -69,9 +75,9 @@
     sm
 }
 
+/// Tests `bytepos_to_file_charpos` in the presence of multi-byte chars.
 #[test]
 fn t6() {
-    // Test bytepos_to_file_charpos in the presence of multi-byte chars
     let sm = init_source_map_mbc();
 
     let cp1 = sm.bytepos_to_file_charpos(BytePos(3));
@@ -87,9 +93,9 @@
     assert_eq!(cp4, CharPos(15));
 }
 
+/// Test `span_to_lines` for a span ending at the end of a `SourceFile`.
 #[test]
 fn t7() {
-    // Test span_to_lines for a span ending at the end of source_file
     let sm = init_source_map();
     let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
     let file_lines = sm.span_to_lines(span).unwrap();
@@ -110,7 +116,7 @@
     Span::with_root_ctxt(BytePos(left_index), BytePos(right_index + 1))
 }
 
-/// Tests span_to_snippet and span_to_lines for a span converting 3
+/// Tests `span_to_snippet` and `span_to_lines` for a span converting 3
 /// lines in the middle of a file.
 #[test]
 fn span_to_snippet_and_lines_spanning_multiple_lines() {
@@ -120,10 +126,10 @@
     sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_string());
     let span = span_from_selection(inputtext, selection);
 
-    // check that we are extracting the text we thought we were extracting
+    // Check that we are extracting the text we thought we were extracting.
     assert_eq!(&sm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD");
 
-    // check that span_to_lines gives us the complete result with the lines/cols we expected
+    // Check that span_to_lines gives us the complete result with the lines/cols we expected.
     let lines = sm.span_to_lines(span).unwrap();
     let expected = vec![
         LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) },
@@ -133,9 +139,9 @@
     assert_eq!(lines.lines, expected);
 }
 
+/// Test span_to_snippet for a span ending at the end of a `SourceFile`.
 #[test]
 fn t8() {
-    // Test span_to_snippet for a span ending at the end of source_file
     let sm = init_source_map();
     let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
     let snippet = sm.span_to_snippet(span);
@@ -143,9 +149,9 @@
     assert_eq!(snippet, Ok("second line".to_string()));
 }
 
+/// Test `span_to_str` for a span ending at the end of a `SourceFile`.
 #[test]
 fn t9() {
-    // Test span_to_str for a span ending at the end of source_file
     let sm = init_source_map();
     let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
     let sstr =  sm.span_to_string(span);
@@ -153,7 +159,7 @@
     assert_eq!(sstr, "blork.rs:2:1: 2:12");
 }
 
-/// Tests failing to merge two spans on different lines
+/// Tests failing to merge two spans on different lines.
 #[test]
 fn span_merging_fail() {
     let sm = SourceMap::new(FilePathMapping::empty());
@@ -167,33 +173,37 @@
     assert!(sm.merge_spans(span1, span2).is_none());
 }
 
-/// Returns the span corresponding to the `n`th occurrence of
-/// `substring` in `source_text`.
+/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`.
 trait SourceMapExtension {
-    fn span_substr(&self,
-                file: &Lrc<SourceFile>,
-                source_text: &str,
-                substring: &str,
-                n: usize)
-                -> Span;
+    fn span_substr(
+        &self,
+        file: &Lrc<SourceFile>,
+        source_text: &str,
+        substring: &str,
+        n: usize,
+    ) -> Span;
 }
 
 impl SourceMapExtension for SourceMap {
-    fn span_substr(&self,
-                file: &Lrc<SourceFile>,
-                source_text: &str,
-                substring: &str,
-                n: usize)
-                -> Span
-    {
-        println!("span_substr(file={:?}/{:?}, substring={:?}, n={})",
-                file.name, file.start_pos, substring, n);
+    fn span_substr(
+        &self,
+        file: &Lrc<SourceFile>,
+        source_text: &str,
+        substring: &str,
+        n: usize,
+    ) -> Span {
+        println!(
+            "span_substr(file={:?}/{:?}, substring={:?}, n={})",
+            file.name, file.start_pos, substring, n
+        );
         let mut i = 0;
         let mut hi = 0;
         loop {
             let offset = source_text[hi..].find(substring).unwrap_or_else(|| {
-                panic!("source_text `{}` does not have {} occurrences of `{}`, only {}",
-                    source_text, n, substring, i);
+                panic!(
+                    "source_text `{}` does not have {} occurrences of `{}`, only {}",
+                    source_text, n, substring, i
+                );
             });
             let lo = hi + offset;
             hi = lo + substring.len();
@@ -202,8 +212,7 @@
                     BytePos(lo as u32 + file.start_pos.0),
                     BytePos(hi as u32 + file.start_pos.0),
                 );
-                assert_eq!(&self.span_to_snippet(span).unwrap()[..],
-                        substring);
+                assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring);
                 return span;
             }
             i += 1;
diff --git a/src/libsyntax/tests.rs b/src/libsyntax/tests.rs
index c472212..540881b 100644
--- a/src/libsyntax/tests.rs
+++ b/src/libsyntax/tests.rs
@@ -18,7 +18,7 @@
 use std::str;
 use std::sync::{Arc, Mutex};
 
-/// Map string to parser (via tts)
+/// Map string to parser (via tts).
 fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
     new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str)
 }
@@ -32,7 +32,7 @@
     x
 }
 
-/// Map a string to tts, using a made-up filename:
+/// Maps a string to tts, using a made-up filename.
 crate fn string_to_stream(source_str: String) -> TokenStream {
     let ps = ParseSess::new(FilePathMapping::empty());
     source_file_to_stream(
@@ -42,7 +42,7 @@
     ), None).0
 }
 
-/// Parse a string, return a crate.
+/// Parses a string, returns a crate.
 crate fn string_to_crate(source_str : String) -> ast::Crate {
     let ps = ParseSess::new(FilePathMapping::empty());
     with_error_checking_parse(source_str, &ps, |p| {
@@ -63,8 +63,8 @@
             (None, None) => return true,
             (None, _) => return false,
             (Some(&a), None) => {
-                if is_pattern_whitespace(a) {
-                    break // trailing whitespace check is out of loop for borrowck
+                if rustc_lexer::is_whitespace(a) {
+                    break // Trailing whitespace check is out of loop for borrowck.
                 } else {
                     return false
                 }
@@ -72,12 +72,12 @@
             (Some(&a), Some(&b)) => (a, b)
         };
 
-        if is_pattern_whitespace(a) && is_pattern_whitespace(b) {
-            // skip whitespace for a and b
+        if rustc_lexer::is_whitespace(a) && rustc_lexer::is_whitespace(b) {
+            // Skip whitespace for `a` and `b`.
             scan_for_non_ws_or_end(&mut a_iter);
             scan_for_non_ws_or_end(&mut b_iter);
-        } else if is_pattern_whitespace(a) {
-            // skip whitespace for a
+        } else if rustc_lexer::is_whitespace(a) {
+            // Skip whitespace for `a`.
             scan_for_non_ws_or_end(&mut a_iter);
         } else if a == b {
             a_iter.next();
@@ -87,22 +87,18 @@
         }
     }
 
-    // check if a has *only* trailing whitespace
-    a_iter.all(is_pattern_whitespace)
+    // Check if a has *only* trailing whitespace.
+    a_iter.all(rustc_lexer::is_whitespace)
 }
 
-/// Advances the given peekable `Iterator` until it reaches a non-whitespace character
+/// Advances the given peekable `Iterator` until it reaches a non-whitespace character.
 fn scan_for_non_ws_or_end<I: Iterator<Item = char>>(iter: &mut Peekable<I>) {
-    while iter.peek().copied().map(|c| is_pattern_whitespace(c)) == Some(true) {
+    while iter.peek().copied().map(|c| rustc_lexer::is_whitespace(c)) == Some(true) {
         iter.next();
     }
 }
 
-fn is_pattern_whitespace(c: char) -> bool {
-    rustc_lexer::character_properties::is_whitespace(c)
-}
-
-/// Identify a position in the text by the Nth occurrence of a string.
+/// Identifies a position in the text by the n'th occurrence of a string.
 struct Position {
     string: &'static str,
     count: usize,
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 0d9f376..d702038 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -6,7 +6,7 @@
 //!
 //! ## Ownership
 //!
-//! `TokenStreams` are persistent data structures constructed as ropes with reference
+//! `TokenStream`s are persistent data structures constructed as ropes with reference
 //! counted-children. In general, this means that calling an operation on a `TokenStream`
 //! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
 //! the original. This essentially coerces `TokenStream`s into 'views' of their subparts,
@@ -147,9 +147,8 @@
     }
 }
 
-/// # Token Streams
-///
 /// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s.
+///
 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
@@ -304,7 +303,7 @@
         Cursor::new(self)
     }
 
-    /// Compares two TokenStreams, checking equality without regarding span information.
+    /// Compares two `TokenStream`s, checking equality without regarding span information.
     pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
         let mut t1 = self.trees();
         let mut t2 = other.trees();
@@ -506,7 +505,7 @@
 
 impl fmt::Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str(&pprust::tokens_to_string(self.clone()))
+        f.write_str(&pprust::tts_to_string(self.clone()))
     }
 }
 
diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs
index a501541..fceaed3 100644
--- a/src/libsyntax/util/parser.rs
+++ b/src/libsyntax/util/parser.rs
@@ -69,7 +69,7 @@
 
 impl AssocOp {
     /// Creates a new AssocOP from a token
-    pub fn from_token(t: &Token) -> Option<AssocOp> {
+    crate fn from_token(t: &Token) -> Option<AssocOp> {
         use AssocOp::*;
         match t.kind {
             token::BinOpEq(k) => Some(AssignOp(k)),
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index ce15683..d7c537b 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -21,13 +21,13 @@
 
 #[derive(Copy, Clone)]
 pub enum FnKind<'a> {
-    /// fn foo() or extern "Abi" fn foo()
+    /// E.g., `fn foo()` or `extern "Abi" fn foo()`.
     ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
 
-    /// fn foo(&self)
+    /// E.g., `fn foo(&self)`.
     Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
 
-    /// |x, y| body
+    /// E.g., `|x, y| body`.
     Closure(&'a Expr),
 }
 
@@ -41,7 +41,7 @@
     }
 }
 
-/// Each method of the Visitor trait is a hook to be potentially
+/// Each method of the `Visitor` trait is a hook to be potentially
 /// overridden. Each method's default implementation recursively visits
 /// the substructure of the input via the corresponding `walk` method;
 /// e.g., the `visit_mod` method by default calls `visit::walk_mod`.
@@ -302,10 +302,12 @@
     walk_list!(visitor, visit_attribute, &item.attrs);
 }
 
-pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V,
-                                 enum_definition: &'a EnumDef,
-                                 _: &'a Generics,
-                                 _: NodeId) {
+pub fn walk_enum_def<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    enum_definition: &'a EnumDef,
+    _: &'a Generics,
+    _: NodeId,
+) {
     walk_list!(visitor, visit_variant, &enum_definition.variants);
 }
 
@@ -342,7 +344,6 @@
             walk_list!(visitor, visit_lifetime, opt_lifetime);
             visitor.visit_ty(&mutable_type.ty)
         }
-        TyKind::Never | TyKind::CVarArgs => {}
         TyKind::Tup(ref tuple_element_types) => {
             walk_list!(visitor, visit_ty, tuple_element_types);
         }
@@ -371,6 +372,8 @@
         TyKind::Mac(ref mac) => {
             visitor.visit_mac(mac)
         }
+        TyKind::Never |
+        TyKind::CVarArgs => {}
     }
 }
 
@@ -386,7 +389,7 @@
     visitor.visit_path(&use_tree.prefix, id);
     match use_tree.kind {
         UseTreeKind::Simple(rename, ..) => {
-            // the extra IDs are handled during HIR lowering
+            // The extra IDs are handled during HIR lowering.
             if let Some(rename) = rename {
                 visitor.visit_ident(rename);
             }
@@ -678,9 +681,8 @@
 }
 
 pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
-    for attr in expression.attrs.iter() {
-        visitor.visit_attribute(attr);
-    }
+    walk_list!(visitor, visit_attribute, expression.attrs.iter());
+
     match expression.node {
         ExprKind::Box(ref subexpression) => {
             visitor.visit_expr(subexpression)
@@ -719,8 +721,8 @@
             visitor.visit_expr(subexpression);
             visitor.visit_ty(typ)
         }
-        ExprKind::Let(ref pats, ref scrutinee) => {
-            walk_list!(visitor, visit_pat, pats);
+        ExprKind::Let(ref pat, ref scrutinee) => {
+            visitor.visit_pat(pat);
             visitor.visit_expr(scrutinee);
         }
         ExprKind::If(ref head_expression, ref if_block, ref optional_else) => {
@@ -831,10 +833,10 @@
 }
 
 pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
-    walk_list!(visitor, visit_pat, &arm.pats);
-    if let Some(ref e) = &arm.guard {
-        visitor.visit_expr(e);
-    }
+    visitor.visit_pat(&arm.pat);
+    // NOTE(or_patterns; Centril | dlrobertson):
+    // If you change this, also change the hack in `lowering.rs`.
+    walk_list!(visitor, visit_expr, &arm.guard);
     visitor.visit_expr(&arm.body);
     walk_list!(visitor, visit_attribute, &arm.attrs);
 }
diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml
index 73310df3..791ee94 100644
--- a/src/libsyntax_ext/Cargo.toml
+++ b/src/libsyntax_ext/Cargo.toml
@@ -18,3 +18,4 @@
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
+rustc_lexer = { path = "../librustc_lexer" }
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index 28f9074..75d727b 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -8,13 +8,12 @@
 
 use syntax::ast;
 use syntax::ext::base::{self, *};
-use syntax::parse;
 use syntax::parse::token::{self, Token};
 use syntax::ptr::P;
 use syntax::symbol::{kw, sym, Symbol};
 use syntax::ast::AsmDialect;
 use syntax_pos::Span;
-use syntax::tokenstream;
+use syntax::tokenstream::{self, TokenStream};
 use syntax::{span_err, struct_span_err};
 
 enum State {
@@ -43,7 +42,7 @@
 
 pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
                        sp: Span,
-                       tts: &[tokenstream::TokenTree])
+                       tts: TokenStream)
                        -> Box<dyn base::MacResult + 'cx> {
     let mut inline_asm = match parse_inline_asm(cx, sp, tts) {
         Ok(Some(inline_asm)) => inline_asm,
@@ -63,7 +62,7 @@
     MacEager::expr(P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
         node: ast::ExprKind::InlineAsm(P(inline_asm)),
-        span: cx.with_legacy_ctxt(sp),
+        span: cx.with_def_site_ctxt(sp),
         attrs: ThinVec::new(),
     }))
 }
@@ -71,20 +70,20 @@
 fn parse_inline_asm<'a>(
     cx: &mut ExtCtxt<'a>,
     sp: Span,
-    tts: &[tokenstream::TokenTree],
+    tts: TokenStream,
 ) -> Result<Option<ast::InlineAsm>, DiagnosticBuilder<'a>> {
     // Split the tts before the first colon, to avoid `asm!("x": y)`  being
     // parsed as `asm!(z)` with `z = "x": y` which is type ascription.
-    let first_colon = tts.iter()
+    let first_colon = tts.trees()
         .position(|tt| {
-            match *tt {
+            match tt {
                 tokenstream::TokenTree::Token(Token { kind: token::Colon, .. }) |
                 tokenstream::TokenTree::Token(Token { kind: token::ModSep, .. }) => true,
                 _ => false,
             }
         })
         .unwrap_or(tts.len());
-    let mut p = cx.new_parser_from_tts(&tts[first_colon..]);
+    let mut p = cx.new_parser_from_tts(tts.trees().skip(first_colon).collect());
     let mut asm = kw::Invalid;
     let mut asm_str_style = None;
     let mut outputs = Vec::new();
@@ -110,7 +109,8 @@
                     ));
                 }
                 // Nested parser, stop before the first colon (see above).
-                let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]);
+                let mut p2 =
+                    cx.new_parser_from_tts(tts.trees().take(first_colon).collect());
 
                 if p2.token == token::Eof {
                     let mut err =
@@ -129,12 +129,8 @@
                 // This is most likely malformed.
                 if p2.token != token::Eof {
                     let mut extra_tts = p2.parse_all_token_trees()?;
-                    extra_tts.extend(tts[first_colon..].iter().cloned());
-                    p = parse::stream_to_parser(
-                        cx.parse_sess,
-                        extra_tts.into_iter().collect(),
-                        Some("inline assembly"),
-                    );
+                    extra_tts.extend(tts.trees().skip(first_colon));
+                    p = cx.new_parser_from_tts(extra_tts.into_iter().collect());
                 }
 
                 asm = s;
diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs
index 84583d0..cbfe14f 100644
--- a/src/libsyntax_ext/assert.rs
+++ b/src/libsyntax_ext/assert.rs
@@ -13,7 +13,7 @@
 pub fn expand_assert<'cx>(
     cx: &'cx mut ExtCtxt<'_>,
     sp: Span,
-    tts: &[TokenTree],
+    tts: TokenStream,
 ) -> Box<dyn MacResult + 'cx> {
     let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) {
         Ok(assert) => assert,
@@ -23,7 +23,9 @@
         }
     };
 
-    let sp = cx.with_legacy_ctxt(sp);
+    // `core::panic` and `std::panic` are different macros, so we use call-site
+    // context to pick up whichever is currently in scope.
+    let sp = cx.with_call_site_ctxt(sp);
     let panic_call = Mac {
         path: Path::from_ident(Ident::new(sym::panic, sp)),
         tts: custom_message.unwrap_or_else(|| {
@@ -59,9 +61,9 @@
 fn parse_assert<'a>(
     cx: &mut ExtCtxt<'a>,
     sp: Span,
-    tts: &[TokenTree]
+    stream: TokenStream
 ) -> Result<Assert, DiagnosticBuilder<'a>> {
-    let mut parser = cx.new_parser_from_tts(tts);
+    let mut parser = cx.new_parser_from_tts(stream);
 
     if parser.token == token::Eof {
         let mut err = cx.struct_span_err(sp, "macro requires a boolean expression as an argument");
diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs
index 21cee8a..3c33baf 100644
--- a/src/libsyntax_ext/cfg.rs
+++ b/src/libsyntax_ext/cfg.rs
@@ -7,16 +7,16 @@
 use syntax::ast;
 use syntax::ext::base::{self, *};
 use syntax::attr;
-use syntax::tokenstream;
+use syntax::tokenstream::TokenStream;
 use syntax::parse::token;
 use syntax_pos::Span;
 
 pub fn expand_cfg(
     cx: &mut ExtCtxt<'_>,
     sp: Span,
-    tts: &[tokenstream::TokenTree],
+    tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'static> {
-    let sp = cx.with_legacy_ctxt(sp);
+    let sp = cx.with_def_site_ctxt(sp);
 
     match parse_cfg(cx, sp, tts) {
         Ok(cfg) => {
@@ -33,7 +33,7 @@
 fn parse_cfg<'a>(
     cx: &mut ExtCtxt<'a>,
     sp: Span,
-    tts: &[tokenstream::TokenTree],
+    tts: TokenStream,
 ) -> Result<ast::MetaItem, DiagnosticBuilder<'a>> {
     let mut p = cx.new_parser_from_tts(tts);
 
diff --git a/src/libsyntax_ext/cmdline_attrs.rs b/src/libsyntax_ext/cmdline_attrs.rs
new file mode 100644
index 0000000..bb8e3df
--- /dev/null
+++ b/src/libsyntax_ext/cmdline_attrs.rs
@@ -0,0 +1,30 @@
+//! Attributes injected into the crate root from command line using `-Z crate-attr`.
+
+use syntax::ast::{self, AttrStyle};
+use syntax::attr::mk_attr;
+use syntax::panictry;
+use syntax::parse::{self, token, ParseSess};
+use syntax_pos::FileName;
+
+pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate {
+    for raw_attr in attrs {
+        let mut parser = parse::new_parser_from_source_str(
+            parse_sess,
+            FileName::cli_crate_attr_source_code(&raw_attr),
+            raw_attr.clone(),
+        );
+
+        let start_span = parser.token.span;
+        let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted());
+        let end_span = parser.token.span;
+        if parser.token != token::Eof {
+            parse_sess.span_diagnostic
+                .span_err(start_span.to(end_span), "invalid crate attribute");
+            continue;
+        }
+
+        krate.attrs.push(mk_attr(AttrStyle::Inner, path, tokens, start_span.to(end_span)));
+    }
+
+    krate
+}
diff --git a/src/libsyntax_ext/compile_error.rs b/src/libsyntax_ext/compile_error.rs
index 59d3f2c..24f3a66 100644
--- a/src/libsyntax_ext/compile_error.rs
+++ b/src/libsyntax_ext/compile_error.rs
@@ -2,11 +2,11 @@
 
 use syntax::ext::base::{self, *};
 use syntax_pos::Span;
-use syntax::tokenstream;
+use syntax::tokenstream::TokenStream;
 
 pub fn expand_compile_error<'cx>(cx: &'cx mut ExtCtxt<'_>,
                               sp: Span,
-                              tts: &[tokenstream::TokenTree])
+                              tts: TokenStream)
                               -> Box<dyn base::MacResult + 'cx> {
     let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") {
         None => return DummyResult::any(sp),
diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs
index ffa5154..16f0160 100644
--- a/src/libsyntax_ext/concat.rs
+++ b/src/libsyntax_ext/concat.rs
@@ -1,14 +1,14 @@
 use syntax::ast;
 use syntax::ext::base::{self, DummyResult};
 use syntax::symbol::Symbol;
-use syntax::tokenstream;
+use syntax::tokenstream::TokenStream;
 
 use std::string::String;
 
-pub fn expand_syntax_ext(
+pub fn expand_concat(
     cx: &mut base::ExtCtxt<'_>,
     sp: syntax_pos::Span,
-    tts: &[tokenstream::TokenTree],
+    tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'static> {
     let es = match base::get_exprs_from_tts(cx, sp, tts) {
         Some(e) => e,
@@ -59,6 +59,6 @@
     } else if has_errors {
         return DummyResult::any(sp);
     }
-    let sp = cx.with_legacy_ctxt(sp);
+    let sp = cx.with_def_site_ctxt(sp);
     base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
 }
diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs
index 9667707..f344706 100644
--- a/src/libsyntax_ext/concat_idents.rs
+++ b/src/libsyntax_ext/concat_idents.rs
@@ -6,21 +6,21 @@
 use syntax::ptr::P;
 use syntax_pos::Span;
 use syntax_pos::symbol::Symbol;
-use syntax::tokenstream::TokenTree;
+use syntax::tokenstream::{TokenTree, TokenStream};
 
-pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt<'_>,
-                              sp: Span,
-                              tts: &[TokenTree])
-                              -> Box<dyn base::MacResult + 'cx> {
+pub fn expand_concat_idents<'cx>(cx: &'cx mut ExtCtxt<'_>,
+                                 sp: Span,
+                                 tts: TokenStream)
+                                 -> Box<dyn base::MacResult + 'cx> {
     if tts.is_empty() {
         cx.span_err(sp, "concat_idents! takes 1 or more arguments.");
         return DummyResult::any(sp);
     }
 
     let mut res_str = String::new();
-    for (i, e) in tts.iter().enumerate() {
+    for (i, e) in tts.into_trees().enumerate() {
         if i & 1 == 1 {
-            match *e {
+            match e {
                 TokenTree::Token(Token { kind: token::Comma, .. }) => {}
                 _ => {
                     cx.span_err(sp, "concat_idents! expecting comma.");
@@ -28,7 +28,7 @@
                 }
             }
         } else {
-            match *e {
+            match e {
                 TokenTree::Token(Token { kind: token::Ident(name, _), .. }) =>
                     res_str.push_str(&name.as_str()),
                 _ => {
@@ -39,7 +39,7 @@
         }
     }
 
-    let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_legacy_ctxt(sp));
+    let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_call_site_ctxt(sp));
 
     struct ConcatIdentsResult { ident: ast::Ident }
 
diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs
index 55687c3..1f4f5aa 100644
--- a/src/libsyntax_ext/deriving/cmp/ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/ord.rs
@@ -95,11 +95,9 @@
                     cx.expr_call_global(span, cmp_path.clone(), args)
                 };
 
-                let eq_arm = cx.arm(span,
-                                    vec![cx.pat_path(span, equals_path.clone())],
-                                    old);
+                let eq_arm = cx.arm(span, cx.pat_path(span, equals_path.clone()), old);
                 let neq_arm = cx.arm(span,
-                                     vec![cx.pat_ident(span, test_id)],
+                                     cx.pat_ident(span, test_id),
                                      cx.expr_ident(span, test_id));
 
                 cx.expr_match(span, new, vec![eq_arm, neq_arm])
diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
index 740b92a..13d63aa 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
@@ -109,7 +109,7 @@
         GtOp => "gt",
         GeOp => "ge",
     };
-    cx.expr_method_call(span, lft, ast::Ident::from_str_and_span(op_str, span), vec![rgt])
+    cx.expr_method_call(span, lft, cx.ident_of(op_str, span), vec![rgt])
 }
 
 pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
@@ -160,10 +160,10 @@
                 };
 
                 let eq_arm = cx.arm(span,
-                                    vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))],
+                                    cx.pat_some(span, cx.pat_path(span, ordering.clone())),
                                     old);
                 let neq_arm = cx.arm(span,
-                                    vec![cx.pat_ident(span, test_id)],
+                                    cx.pat_ident(span, test_id),
                                     cx.expr_ident(span, test_id));
 
                 cx.expr_match(span, new, vec![eq_arm, neq_arm])
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 781645a..088b61b 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -62,7 +62,7 @@
     // We want to make sure we have the ctxt set so that we can use unstable methods
     let span = cx.with_def_site_ctxt(span);
     let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
-    let builder = Ident::from_str_and_span("debug_trait_builder", span);
+    let builder = cx.ident_of("debug_trait_builder", span);
     let builder_expr = cx.expr_ident(span, builder.clone());
 
     let fmt = substr.nonself_args[0].clone();
@@ -72,7 +72,7 @@
         ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
             // tuple struct/"normal" variant
             let expr =
-                cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
+                cx.expr_method_call(span, fmt, cx.ident_of("debug_tuple", span), vec![name]);
             stmts.push(cx.stmt_let(span, true, builder, expr));
 
             for field in fields {
@@ -93,7 +93,7 @@
         ast::VariantData::Struct(..) => {
             // normal struct/struct variant
             let expr =
-                cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
+                cx.expr_method_call(span, fmt, cx.ident_of("debug_struct", span), vec![name]);
             stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
 
             for field in fields {
@@ -113,7 +113,7 @@
         }
     }
 
-    let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]);
+    let expr = cx.expr_method_call(span, builder_expr, cx.ident_of("finish", span), vec![]);
 
     stmts.push(cx.stmt_expr(expr));
     let block = cx.block(span, stmts);
diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs
index 9b6f851..cde72ab 100644
--- a/src/libsyntax_ext/deriving/decodable.rs
+++ b/src/libsyntax_ext/deriving/decodable.rs
@@ -66,10 +66,14 @@
                           krate: &str)
                           -> P<Expr> {
     let decoder = substr.nonself_args[0].clone();
-    let recurse = vec![cx.ident_of(krate), cx.ident_of("Decodable"), cx.ident_of("decode")];
+    let recurse = vec![
+        cx.ident_of(krate, trait_span),
+        cx.ident_of("Decodable", trait_span),
+        cx.ident_of("decode", trait_span),
+    ];
     let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse));
     // throw an underscore in front to suppress unused variable warnings
-    let blkarg = cx.ident_of("_d");
+    let blkarg = cx.ident_of("_d", trait_span);
     let blkdecoder = cx.expr_ident(trait_span, blkarg);
 
     return match *substr.fields {
@@ -78,7 +82,7 @@
                 Unnamed(ref fields, _) => fields.len(),
                 Named(ref fields) => fields.len(),
             };
-            let read_struct_field = cx.ident_of("read_struct_field");
+            let read_struct_field = cx.ident_of("read_struct_field", trait_span);
 
             let path = cx.path_ident(trait_span, substr.type_ident);
             let result =
@@ -94,17 +98,17 @@
             let result = cx.expr_ok(trait_span, result);
             cx.expr_method_call(trait_span,
                                 decoder,
-                                cx.ident_of("read_struct"),
+                                cx.ident_of("read_struct", trait_span),
                                 vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.expr_usize(trait_span, nfields),
                                      cx.lambda1(trait_span, result, blkarg)])
         }
         StaticEnum(_, ref fields) => {
-            let variant = cx.ident_of("i");
+            let variant = cx.ident_of("i", trait_span);
 
             let mut arms = Vec::with_capacity(fields.len() + 1);
             let mut variants = Vec::with_capacity(fields.len());
-            let rvariant_arg = cx.ident_of("read_enum_variant_arg");
+            let rvariant_arg = cx.ident_of("read_enum_variant_arg", trait_span);
 
             for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() {
                 variants.push(cx.expr_str(v_span, ident.name));
@@ -119,9 +123,7 @@
                                                     vec![idx, exprdecode.clone()]))
                 });
 
-                arms.push(cx.arm(v_span,
-                                 vec![cx.pat_lit(v_span, cx.expr_usize(v_span, i))],
-                                 decoded));
+                arms.push(cx.arm(v_span, cx.pat_lit(v_span, cx.expr_usize(v_span, i)), decoded));
             }
 
             arms.push(cx.arm_unreachable(trait_span));
@@ -134,11 +136,11 @@
             let variant_vec = cx.expr_addr_of(trait_span, variant_vec);
             let result = cx.expr_method_call(trait_span,
                                              blkdecoder,
-                                             cx.ident_of("read_enum_variant"),
+                                             cx.ident_of("read_enum_variant", trait_span),
                                              vec![variant_vec, lambda]);
             cx.expr_method_call(trait_span,
                                 decoder,
-                                cx.ident_of("read_enum"),
+                                cx.ident_of("read_enum", trait_span),
                                 vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.lambda1(trait_span, result, blkarg)])
         }
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 8b18fb2..655d3bb 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -153,16 +153,16 @@
                           -> P<Expr> {
     let encoder = substr.nonself_args[0].clone();
     // throw an underscore in front to suppress unused variable warnings
-    let blkarg = cx.ident_of("_e");
+    let blkarg = cx.ident_of("_e", trait_span);
     let blkencoder = cx.expr_ident(trait_span, blkarg);
     let fn_path = cx.expr_path(cx.path_global(trait_span,
-                                              vec![cx.ident_of(krate),
-                                                   cx.ident_of("Encodable"),
-                                                   cx.ident_of("encode")]));
+                                              vec![cx.ident_of(krate, trait_span),
+                                                   cx.ident_of("Encodable", trait_span),
+                                                   cx.ident_of("encode", trait_span)]));
 
     return match *substr.fields {
         Struct(_, ref fields) => {
-            let emit_struct_field = cx.ident_of("emit_struct_field");
+            let emit_struct_field = cx.ident_of("emit_struct_field", trait_span);
             let mut stmts = Vec::new();
             for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() {
                 let name = match name {
@@ -201,7 +201,7 @@
 
             cx.expr_method_call(trait_span,
                                 encoder,
-                                cx.ident_of("emit_struct"),
+                                cx.ident_of("emit_struct", trait_span),
                                 vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.expr_usize(trait_span, fields.len()),
                                      blk])
@@ -214,7 +214,7 @@
             // actually exist.
             let me = cx.stmt_let(trait_span, false, blkarg, encoder);
             let encoder = cx.expr_ident(trait_span, blkarg);
-            let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
+            let emit_variant_arg = cx.ident_of("emit_enum_variant_arg", trait_span);
             let mut stmts = Vec::new();
             if !fields.is_empty() {
                 let last = fields.len() - 1;
@@ -244,7 +244,7 @@
             let name = cx.expr_str(trait_span, variant.ident.name);
             let call = cx.expr_method_call(trait_span,
                                            blkencoder,
-                                           cx.ident_of("emit_enum_variant"),
+                                           cx.ident_of("emit_enum_variant", trait_span),
                                            vec![name,
                                                 cx.expr_usize(trait_span, idx),
                                                 cx.expr_usize(trait_span, fields.len()),
@@ -252,7 +252,7 @@
             let blk = cx.lambda1(trait_span, call, blkarg);
             let ret = cx.expr_method_call(trait_span,
                                           encoder,
-                                          cx.ident_of("emit_enum"),
+                                          cx.ident_of("emit_enum", trait_span),
                                           vec![cx.expr_str(trait_span ,substr.type_ident.name),
                                                blk]);
             cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)]))
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 6fd763f..aceee62 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -237,7 +237,7 @@
     /// Whether there is a self argument (outer Option) i.e., whether
     /// this is a static function, and whether it is a pointer (inner
     /// Option)
-    pub explicit_self: Option<Option<PtrTy<'a>>>,
+    pub explicit_self: Option<Option<PtrTy>>,
 
     /// Arguments other than the self argument
     pub args: Vec<(Ty<'a>, &'a str)>,
@@ -843,7 +843,7 @@
                                 -> P<Expr> {
         let substructure = Substructure {
             type_ident,
-            method_ident: cx.ident_of(self.name),
+            method_ident: cx.ident_of(self.name, trait_.span),
             self_args,
             nonself_args,
             fields,
@@ -890,7 +890,7 @@
 
         for (ty, name) in self.args.iter() {
             let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
-            let ident = ast::Ident::from_str_and_span(name, trait_.span);
+            let ident = cx.ident_of(name, trait_.span);
             arg_tys.push((ident, ast_ty));
 
             let arg_expr = cx.expr_ident(trait_.span, ident);
@@ -938,7 +938,7 @@
 
         let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
 
-        let method_ident = cx.ident_of(self.name);
+        let method_ident = cx.ident_of(self.name, trait_.span);
         let fn_decl = cx.fn_decl(args, ast::FunctionRetTy::Ty(ret_type));
         let body_block = cx.block_expr(body);
 
@@ -1071,7 +1071,7 @@
         for (arg_expr, pat) in self_args.iter().zip(patterns) {
             body = cx.expr_match(trait_.span,
                                  arg_expr.clone(),
-                                 vec![cx.arm(trait_.span, vec![pat.clone()], body)])
+                                 vec![cx.arm(trait_.span, pat.clone(), body)])
         }
 
         body
@@ -1201,7 +1201,7 @@
             ).collect::<Vec<String>>();
 
         let self_arg_idents = self_arg_names.iter()
-            .map(|name| cx.ident_of(&name[..]))
+            .map(|name| cx.ident_of(name, sp))
             .collect::<Vec<ast::Ident>>();
 
         // The `vi_idents` will be bound, solely in the catch-all, to
@@ -1210,7 +1210,7 @@
         let vi_idents = self_arg_names.iter()
             .map(|name| {
                 let vi_suffix = format!("{}_vi", &name[..]);
-                ast::Ident::from_str_and_span(&vi_suffix[..], trait_.span)
+                cx.ident_of(&vi_suffix[..], trait_.span)
             })
             .collect::<Vec<ast::Ident>>();
 
@@ -1311,7 +1311,7 @@
                                                              nonself_args,
                                                              &substructure);
 
-                cx.arm(sp, vec![single_pat], arm_expr)
+                cx.arm(sp, single_pat, arm_expr)
             })
             .collect();
 
@@ -1337,7 +1337,7 @@
             _ => None,
         };
         if let Some(arm) = default {
-            match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], arm));
+            match_arms.push(cx.arm(sp, cx.pat_wild(sp), arm));
         }
 
         // We will usually need the catch-all after matching the
@@ -1389,7 +1389,7 @@
 
                 let target_ty = cx.ty_ident(
                     sp,
-                    ast::Ident::from_str_and_span(target_type_name, sp),
+                    cx.ident_of(target_type_name, sp),
                 );
                 let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
                 let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
@@ -1591,7 +1591,7 @@
         let mut ident_exprs = Vec::new();
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = struct_field.span.with_ctxt(self.span.ctxt());
-            let ident = ast::Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span);
+            let ident = cx.ident_of(&format!("{}_{}", prefix, i), self.span);
             paths.push(ident.with_span_pos(sp));
             let val = cx.expr_path(cx.path_ident(sp, ident));
             let val = if use_temporaries {
@@ -1620,6 +1620,7 @@
                             id: ast::DUMMY_NODE_ID,
                             span: pat.span.with_ctxt(self.span.ctxt()),
                             pat,
+                            is_placeholder: false
                         }
                     })
                     .collect();
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index cb1c7b2..b341a07 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -13,9 +13,9 @@
 
 /// The types of pointers
 #[derive(Clone)]
-pub enum PtrTy<'a> {
+pub enum PtrTy {
     /// &'lifetime mut
-    Borrowed(Option<&'a str>, ast::Mutability),
+    Borrowed(Option<Ident>, ast::Mutability),
     /// *mut
     #[allow(dead_code)]
     Raw(ast::Mutability),
@@ -26,7 +26,7 @@
 #[derive(Clone)]
 pub struct Path<'a> {
     path: Vec<&'a str>,
-    lifetime: Option<&'a str>,
+    lifetime: Option<Ident>,
     params: Vec<Box<Ty<'a>>>,
     kind: PathKind,
 }
@@ -46,7 +46,7 @@
         Path::new_(vec![path], None, Vec::new(), PathKind::Local)
     }
     pub fn new_<'r>(path: Vec<&'r str>,
-                    lifetime: Option<&'r str>,
+                    lifetime: Option<Ident>,
                     params: Vec<Box<Ty<'r>>>,
                     kind: PathKind)
                     -> Path<'r> {
@@ -72,7 +72,7 @@
                    self_ty: Ident,
                    self_generics: &Generics)
                    -> ast::Path {
-        let mut idents = self.path.iter().map(|s| Ident::from_str_and_span(*s, span)).collect();
+        let mut idents = self.path.iter().map(|s| cx.ident_of(*s, span)).collect();
         let lt = mk_lifetimes(cx, span, &self.lifetime);
         let tys: Vec<P<ast::Ty>> =
             self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
@@ -99,7 +99,7 @@
 pub enum Ty<'a> {
     Self_,
     /// &/Box/ Ty
-    Ptr(Box<Ty<'a>>, PtrTy<'a>),
+    Ptr(Box<Ty<'a>>, PtrTy),
     /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
     /// parameter, and things like `i32`
     Literal(Path<'a>),
@@ -107,14 +107,14 @@
     Tuple(Vec<Ty<'a>>),
 }
 
-pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
+pub fn borrowed_ptrty() -> PtrTy {
     Borrowed(None, ast::Mutability::Immutable)
 }
 pub fn borrowed(ty: Box<Ty<'_>>) -> Ty<'_> {
     Ptr(ty, borrowed_ptrty())
 }
 
-pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
+pub fn borrowed_explicit_self() -> Option<Option<PtrTy>> {
     Some(Some(borrowed_ptrty()))
 }
 
@@ -126,13 +126,11 @@
     Tuple(Vec::new())
 }
 
-fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
-    lt.map(|s|
-        cx.lifetime(span, Ident::from_str(s))
-    )
+fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Option<ast::Lifetime> {
+    lt.map(|ident| cx.lifetime(span, ident))
 }
 
-fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
+fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Vec<ast::Lifetime> {
     mk_lifetime(cx, span, lt).into_iter().collect()
 }
 
@@ -209,7 +207,7 @@
             cx.trait_bound(path)
         })
         .collect();
-    cx.typaram(span, ast::Ident::from_str_and_span(name, span), attrs.to_owned(), bounds, None)
+    cx.typaram(span, cx.ident_of(name, span), attrs.to_owned(), bounds, None)
 }
 
 fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
@@ -265,7 +263,7 @@
 
 pub fn get_explicit_self(cx: &ExtCtxt<'_>,
                          span: Span,
-                         self_ptr: &Option<PtrTy<'_>>)
+                         self_ptr: &Option<PtrTy>)
                          -> (P<Expr>, ast::ExplicitSelf) {
     // this constructs a fresh `self` path
     let self_path = cx.expr_self(span);
@@ -276,7 +274,7 @@
                 respan(span,
                        match *ptr {
                            Borrowed(ref lt, mutbl) => {
-                               let lt = lt.map(|s| cx.lifetime(span, Ident::from_str(s)));
+                               let lt = lt.map(|s| cx.lifetime(span, s));
                                SelfKind::Region(lt, mutbl)
                            }
                            Raw(_) => {
diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs
index 6343d21..70e1fbe 100644
--- a/src/libsyntax_ext/env.rs
+++ b/src/libsyntax_ext/env.rs
@@ -7,29 +7,29 @@
 use syntax::ext::base::{self, *};
 use syntax::symbol::{kw, sym, Symbol};
 use syntax_pos::Span;
-use syntax::tokenstream;
+use syntax::tokenstream::TokenStream;
 
 use std::env;
 
 pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>,
                               sp: Span,
-                              tts: &[tokenstream::TokenTree])
+                              tts: TokenStream)
                               -> Box<dyn base::MacResult + 'cx> {
     let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
         None => return DummyResult::any(sp),
         Some(v) => v,
     };
 
-    let sp = cx.with_legacy_ctxt(sp);
+    let sp = cx.with_def_site_ctxt(sp);
     let e = match env::var(&*var.as_str()) {
         Err(..) => {
-            let lt = cx.lifetime(sp, Ident::with_dummy_span(kw::StaticLifetime));
+            let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp));
             cx.expr_path(cx.path_all(sp,
                                      true,
                                      cx.std_path(&[sym::option, sym::Option, sym::None]),
                                      vec![GenericArg::Type(cx.ty_rptr(sp,
                                                      cx.ty_ident(sp,
-                                                                 Ident::with_dummy_span(sym::str)),
+                                                                 Ident::new(sym::str, sp)),
                                                      Some(lt),
                                                      ast::Mutability::Immutable))],
                                      vec![]))
@@ -45,7 +45,7 @@
 
 pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt<'_>,
                        sp: Span,
-                       tts: &[tokenstream::TokenTree])
+                       tts: TokenStream)
                        -> Box<dyn base::MacResult + 'cx> {
     let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
         Some(ref exprs) if exprs.is_empty() => {
diff --git a/src/libsyntax_ext/error_codes.rs b/src/libsyntax_ext/error_codes.rs
index 5982a4d..2bc9905 100644
--- a/src/libsyntax_ext/error_codes.rs
+++ b/src/libsyntax_ext/error_codes.rs
@@ -1,9 +1,8 @@
-use syntax::register_long_diagnostics;
-
 // Error messages for EXXXX errors.
-// Each message should start and end with a new line, and be wrapped to 80 characters.
-// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
-register_long_diagnostics! {
+// Each message should start and end with a new line, and be wrapped to 80
+// characters.  In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use
+// `:set tw=0` to disable.
+syntax::register_diagnostics! {
 E0660: r##"
 The argument to the `asm` macro is not well-formed.
 
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 47394c0..46c7cbb 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -11,7 +11,7 @@
 use syntax::parse::token;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, sym};
-use syntax::tokenstream;
+use syntax::tokenstream::TokenStream;
 use syntax_pos::{MultiSpan, Span};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -126,7 +126,7 @@
 fn parse_args<'a>(
     ecx: &mut ExtCtxt<'a>,
     sp: Span,
-    tts: &[tokenstream::TokenTree]
+    tts: TokenStream,
 ) -> Result<(P<ast::Expr>, Vec<P<ast::Expr>>, FxHashMap<Symbol, usize>), DiagnosticBuilder<'a>> {
     let mut args = Vec::<P<ast::Expr>>::new();
     let mut names = FxHashMap::<Symbol, usize>::default();
@@ -138,15 +138,23 @@
     }
 
     let fmtstr = p.parse_expr()?;
+    let mut first = true;
     let mut named = false;
 
     while p.token != token::Eof {
         if !p.eat(&token::Comma) {
-            let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`");
-            err.span_label(p.token.span, "expected `,`");
-            p.maybe_annotate_with_ascription(&mut err, false);
-            return Err(err);
+            if first {
+                // After `format!(""` we always expect *only* a comma...
+                let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`");
+                err.span_label(p.token.span, "expected `,`");
+                p.maybe_annotate_with_ascription(&mut err, false);
+                return Err(err);
+            } else {
+                // ...after that delegate to `expect` to also include the other expected tokens.
+                return Err(p.expect(&token::Comma).err().unwrap());
+            }
         }
+        first = false;
         if p.token == token::Eof {
             break;
         } // accept trailing commas
@@ -291,7 +299,7 @@
                 &format!(
                     "{} positional argument{} in format string, but {}",
                     count,
-                    if count > 1 { "s" } else { "" },
+                    if count != 1 { "s" } else { "" },
                     self.describe_num_args(),
                 ),
             );
@@ -478,7 +486,7 @@
         let sp = self.macsp;
         let count = |c, arg| {
             let mut path = Context::rtpath(self.ecx, "Count");
-            path.push(self.ecx.ident_of(c));
+            path.push(self.ecx.ident_of(c, sp));
             match arg {
                 Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]),
                 None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
@@ -526,7 +534,7 @@
                 let pos = {
                     let pos = |c, arg| {
                         let mut path = Context::rtpath(self.ecx, "Position");
-                        path.push(self.ecx.ident_of(c));
+                        path.push(self.ecx.ident_of(c, sp));
                         match arg {
                             Some(i) => {
                                 let arg = self.ecx.expr_usize(sp, i);
@@ -595,7 +603,7 @@
                 let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill));
                 let align = |name| {
                     let mut p = Context::rtpath(self.ecx, "Alignment");
-                    p.push(self.ecx.ident_of(name));
+                    p.push(self.ecx.ident_of(name, sp));
                     self.ecx.path_global(sp, p)
                 };
                 let align = match arg.format.align {
@@ -613,11 +621,11 @@
                     sp,
                     path,
                     vec![
-                        self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("align"), align),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("flags"), flags),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("precision"), prec),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("width"), width),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("fill", sp), fill),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("align", sp), align),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("flags", sp), flags),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("precision", sp), prec),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("width", sp), width),
                     ],
                 );
 
@@ -626,8 +634,8 @@
                     sp,
                                           path,
                     vec![
-                        self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("position", sp), pos),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("format", sp), fmt),
                     ],
                 ))
             }
@@ -645,7 +653,7 @@
         let mut heads = Vec::with_capacity(self.args.len());
 
         let names_pos: Vec<_> = (0..self.args.len())
-            .map(|i| ast::Ident::from_str_and_span(&format!("arg{}", i), self.macsp))
+            .map(|i| self.ecx.ident_of(&format!("arg{}", i), self.macsp))
             .collect();
 
         // First, build up the static array which will become our precompiled
@@ -716,7 +724,7 @@
         // But the nested match expression is proved to perform not as well
         // as series of let's; the first approach does.
         let pat = self.ecx.pat_tuple(self.fmtsp, pats);
-        let arm = self.ecx.arm(self.fmtsp, vec![pat], args_array);
+        let arm = self.ecx.arm(self.fmtsp, pat, args_array);
         let head = self.ecx.expr(self.fmtsp, ast::ExprKind::Tup(heads));
         let result = self.ecx.expr_match(self.fmtsp, head, vec![arm]);
 
@@ -794,7 +802,7 @@
 fn expand_format_args_impl<'cx>(
     ecx: &'cx mut ExtCtxt<'_>,
     mut sp: Span,
-    tts: &[tokenstream::TokenTree],
+    tts: TokenStream,
     nl: bool,
 ) -> Box<dyn base::MacResult + 'cx> {
     sp = ecx.with_def_site_ctxt(sp);
@@ -812,7 +820,7 @@
 pub fn expand_format_args<'cx>(
     ecx: &'cx mut ExtCtxt<'_>,
     sp: Span,
-    tts: &[tokenstream::TokenTree],
+    tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'cx> {
     expand_format_args_impl(ecx, sp, tts, false)
 }
@@ -820,7 +828,7 @@
 pub fn expand_format_args_nl<'cx>(
     ecx: &'cx mut ExtCtxt<'_>,
     sp: Span,
-    tts: &[tokenstream::TokenTree],
+    tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'cx> {
     expand_format_args_impl(ecx, sp, tts, true)
 }
diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs
index f4af169..19a87e6 100644
--- a/src/libsyntax_ext/global_allocator.rs
+++ b/src/libsyntax_ext/global_allocator.rs
@@ -28,7 +28,7 @@
     };
 
     // Generate a bunch of new items using the AllocFnFactory
-    let span = ecx.with_legacy_ctxt(item.span);
+    let span = ecx.with_def_site_ctxt(item.span);
     let f = AllocFnFactory {
         span,
         kind: AllocatorKind::Global,
@@ -43,7 +43,7 @@
     let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
     let const_body = ecx.expr_block(ecx.block(span, stmts));
     let const_item =
-        ecx.item_const(span, Ident::with_dummy_span(kw::Underscore), const_ty, const_body);
+        ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
 
     // Return the original item and the new methods.
     vec![Annotatable::Item(item), Annotatable::Item(const_item)]
@@ -61,7 +61,7 @@
         let mut abi_args = Vec::new();
         let mut i = 0;
         let ref mut mk = || {
-            let name = Ident::from_str(&format!("arg{}", i));
+            let name = self.cx.ident_of(&format!("arg{}", i), self.span);
             i += 1;
             name
         };
@@ -83,7 +83,7 @@
         );
         let item = self.cx.item(
             self.span,
-            Ident::from_str(&self.kind.fn_name(method.name)),
+            self.cx.ident_of(&self.kind.fn_name(method.name), self.span),
             self.attrs(),
             kind,
         );
@@ -119,7 +119,7 @@
     ) -> P<Expr> {
         match *ty {
             AllocatorTy::Layout => {
-                let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
+                let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
                 let ty_usize = self.cx.ty_path(usize);
                 let size = ident();
                 let align = ident();
@@ -177,12 +177,12 @@
     }
 
     fn usize(&self) -> P<Ty> {
-        let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
+        let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
         self.cx.ty_path(usize)
     }
 
     fn ptr_u8(&self) -> P<Ty> {
-        let u8 = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::u8));
+        let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span));
         let ty_u8 = self.cx.ty_path(u8);
         self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
     }
diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs
index a8b6159..c56b3f3 100644
--- a/src/libsyntax_ext/global_asm.rs
+++ b/src/libsyntax_ext/global_asm.rs
@@ -16,12 +16,12 @@
 use syntax::parse::token;
 use syntax::ptr::P;
 use syntax_pos::Span;
-use syntax::tokenstream;
+use syntax::tokenstream::TokenStream;
 use smallvec::smallvec;
 
 pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
                               sp: Span,
-                              tts: &[tokenstream::TokenTree]) -> Box<dyn base::MacResult + 'cx> {
+                              tts: TokenStream) -> Box<dyn base::MacResult + 'cx> {
     match parse_global_asm(cx, sp, tts) {
         Ok(Some(global_asm)) => {
             MacEager::items(smallvec![P(ast::Item {
@@ -30,7 +30,7 @@
                 id: ast::DUMMY_NODE_ID,
                 node: ast::ItemKind::GlobalAsm(P(global_asm)),
                 vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
-                span: cx.with_legacy_ctxt(sp),
+                span: cx.with_def_site_ctxt(sp),
                 tokens: None,
             })])
         }
@@ -45,7 +45,7 @@
 fn parse_global_asm<'a>(
     cx: &mut ExtCtxt<'a>,
     sp: Span,
-    tts: &[tokenstream::TokenTree]
+    tts: TokenStream
 ) -> Result<Option<ast::GlobalAsm>, DiagnosticBuilder<'a>> {
     let mut p = cx.new_parser_from_tts(tts);
 
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 1a617691..631ab7a 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -9,7 +9,6 @@
 #![feature(nll)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
-#![feature(rustc_diagnostic_macros)]
 
 extern crate proc_macro;
 
@@ -40,6 +39,7 @@
 mod test;
 mod trace_macros;
 
+pub mod cmdline_attrs;
 pub mod plugin_macro_defs;
 pub mod proc_macro_harness;
 pub mod standard_library_imports;
@@ -67,8 +67,8 @@
         cfg: cfg::expand_cfg,
         column: source_util::expand_column,
         compile_error: compile_error::expand_compile_error,
-        concat_idents: concat_idents::expand_syntax_ext,
-        concat: concat::expand_syntax_ext,
+        concat_idents: concat_idents::expand_concat_idents,
+        concat: concat::expand_concat,
         env: env::expand_env,
         file: source_util::expand_file,
         format_args_nl: format::expand_format_args_nl,
@@ -78,7 +78,7 @@
         include_str: source_util::expand_include_str,
         include: source_util::expand_include,
         line: source_util::expand_line,
-        log_syntax: log_syntax::expand_syntax_ext,
+        log_syntax: log_syntax::expand_log_syntax,
         module_path: source_util::expand_mod,
         option_env: env::expand_option_env,
         stringify: source_util::expand_stringify,
diff --git a/src/libsyntax_ext/log_syntax.rs b/src/libsyntax_ext/log_syntax.rs
index cbdfd08..92130bf 100644
--- a/src/libsyntax_ext/log_syntax.rs
+++ b/src/libsyntax_ext/log_syntax.rs
@@ -1,11 +1,11 @@
 use syntax::ext::base;
 use syntax::print;
-use syntax::tokenstream;
+use syntax::tokenstream::TokenStream;
 use syntax_pos;
 
-pub fn expand_syntax_ext<'cx>(_cx: &'cx mut base::ExtCtxt<'_>,
+pub fn expand_log_syntax<'cx>(_cx: &'cx mut base::ExtCtxt<'_>,
                               sp: syntax_pos::Span,
-                              tts: &[tokenstream::TokenTree])
+                              tts: TokenStream)
                               -> Box<dyn base::MacResult + 'cx> {
     println!("{}", print::pprust::tts_to_string(tts));
 
diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs
index dbfd8fe..ccdc5bd 100644
--- a/src/libsyntax_ext/plugin_macro_defs.rs
+++ b/src/libsyntax_ext/plugin_macro_defs.rs
@@ -11,7 +11,7 @@
 use syntax::symbol::sym;
 use syntax::tokenstream::*;
 use syntax_pos::{Span, DUMMY_SP};
-use syntax_pos::hygiene::{ExpnData, ExpnKind, MacroKind};
+use syntax_pos::hygiene::{ExpnData, ExpnKind, AstPass};
 
 use std::mem;
 
@@ -44,7 +44,7 @@
     if !named_exts.is_empty() {
         let mut extra_items = Vec::new();
         let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
-            ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition,
+            ExpnKind::AstPass(AstPass::PluginMacroDefs), DUMMY_SP, edition,
             [sym::rustc_attrs][..].into(),
         ));
         for (name, ext) in named_exts {
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
index e772eaf..f33c813 100644
--- a/src/libsyntax_ext/proc_macro_harness.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -3,8 +3,7 @@
 use smallvec::smallvec;
 use syntax::ast::{self, Ident};
 use syntax::attr;
-use syntax::source_map::{ExpnData, ExpnKind, respan};
-use syntax::ext::base::{ExtCtxt, MacroKind};
+use syntax::ext::base::ExtCtxt;
 use syntax::ext::expand::{AstFragment, ExpansionConfig};
 use syntax::ext::proc_macro::is_proc_macro_attr;
 use syntax::parse::ParseSess;
@@ -12,6 +11,7 @@
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::hygiene::AstPass;
 
 struct ProcMacroDerive {
     trait_name: ast::Name,
@@ -20,15 +20,24 @@
     attrs: Vec<ast::Name>,
 }
 
+enum ProcMacroDefType {
+    Attr,
+    Bang
+}
+
 struct ProcMacroDef {
     function_name: Ident,
     span: Span,
+    def_type: ProcMacroDefType
+}
+
+enum ProcMacro {
+    Derive(ProcMacroDerive),
+    Def(ProcMacroDef)
 }
 
 struct CollectProcMacros<'a> {
-    derives: Vec<ProcMacroDerive>,
-    attr_macros: Vec<ProcMacroDef>,
-    bang_macros: Vec<ProcMacroDef>,
+    macros: Vec<ProcMacro>,
     in_root: bool,
     handler: &'a errors::Handler,
     is_proc_macro_crate: bool,
@@ -46,22 +55,22 @@
     let ecfg = ExpansionConfig::default("proc_macro".to_string());
     let mut cx = ExtCtxt::new(sess, ecfg, resolver);
 
-    let (derives, attr_macros, bang_macros) = {
-        let mut collect = CollectProcMacros {
-            derives: Vec::new(),
-            attr_macros: Vec::new(),
-            bang_macros: Vec::new(),
-            in_root: true,
-            handler,
-            is_proc_macro_crate,
-            is_test_crate,
-        };
-        if has_proc_macro_decls || is_proc_macro_crate {
-            visit::walk_crate(&mut collect, &krate);
-        }
-        (collect.derives, collect.attr_macros, collect.bang_macros)
+    let mut collect = CollectProcMacros {
+        macros: Vec::new(),
+        in_root: true,
+        handler,
+        is_proc_macro_crate,
+        is_test_crate,
     };
 
+    if has_proc_macro_decls || is_proc_macro_crate {
+        visit::walk_crate(&mut collect, &krate);
+    }
+    // NOTE: If you change the order of macros in this vec
+    // for any reason, you must also update 'raw_proc_macro'
+    // in src/librustc_metadata/decoder.rs
+    let macros = collect.macros;
+
     if !is_proc_macro_crate {
         return krate
     }
@@ -74,7 +83,7 @@
         return krate;
     }
 
-    krate.module.items.push(mk_decls(&mut cx, &derives, &attr_macros, &bang_macros));
+    krate.module.items.push(mk_decls(&mut cx, &macros));
 
     krate
 }
@@ -161,12 +170,12 @@
         };
 
         if self.in_root && item.vis.node.is_pub() {
-            self.derives.push(ProcMacroDerive {
+            self.macros.push(ProcMacro::Derive(ProcMacroDerive {
                 span: item.span,
                 trait_name: trait_ident.name,
                 function_name: item.ident,
                 attrs: proc_attrs,
-            });
+            }));
         } else {
             let msg = if !self.in_root {
                 "functions tagged with `#[proc_macro_derive]` must \
@@ -180,10 +189,11 @@
 
     fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
         if self.in_root && item.vis.node.is_pub() {
-            self.attr_macros.push(ProcMacroDef {
+            self.macros.push(ProcMacro::Def(ProcMacroDef {
                 span: item.span,
                 function_name: item.ident,
-            });
+                def_type: ProcMacroDefType::Attr
+            }));
         } else {
             let msg = if !self.in_root {
                 "functions tagged with `#[proc_macro_attribute]` must \
@@ -197,10 +207,11 @@
 
     fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
         if self.in_root && item.vis.node.is_pub() {
-            self.bang_macros.push(ProcMacroDef {
+            self.macros.push(ProcMacro::Def(ProcMacroDef {
                 span: item.span,
                 function_name: item.ident,
-            });
+                def_type: ProcMacroDefType::Bang
+            }));
         } else {
             let msg = if !self.in_root {
                 "functions tagged with `#[proc_macro]` must \
@@ -308,8 +319,7 @@
 
 // Creates a new module which looks like:
 //
-//      #[doc(hidden)]
-//      mod $gensym {
+//      const _: () = {
 //          extern crate proc_macro;
 //
 //          use proc_macro::bridge::client::ProcMacro;
@@ -323,65 +333,67 @@
 //      }
 fn mk_decls(
     cx: &mut ExtCtxt<'_>,
-    custom_derives: &[ProcMacroDerive],
-    custom_attrs: &[ProcMacroDef],
-    custom_macros: &[ProcMacroDef],
+    macros: &[ProcMacro],
 ) -> P<ast::Item> {
-    let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
-        ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition,
-        [sym::rustc_attrs, sym::proc_macro_internals][..].into(),
-    ));
+    let expn_id = cx.resolver.expansion_for_ast_pass(
+        DUMMY_SP,
+        AstPass::ProcMacroHarness,
+        &[sym::rustc_attrs, sym::proc_macro_internals],
+        None,
+    );
+    let span = DUMMY_SP.with_def_site_ctxt(expn_id);
 
-    let hidden = cx.meta_list_item_word(span, sym::hidden);
-    let doc = cx.meta_list(span, sym::doc, vec![hidden]);
-    let doc_hidden = cx.attribute(doc);
-
-    let proc_macro = Ident::with_dummy_span(sym::proc_macro);
+    let proc_macro = Ident::new(sym::proc_macro, span);
     let krate = cx.item(span,
                         proc_macro,
                         Vec::new(),
                         ast::ItemKind::ExternCrate(None));
 
-    let bridge = Ident::from_str("bridge");
-    let client = Ident::from_str("client");
-    let proc_macro_ty = Ident::from_str("ProcMacro");
-    let custom_derive = Ident::from_str("custom_derive");
-    let attr = Ident::from_str("attr");
-    let bang = Ident::from_str("bang");
-    let crate_kw = Ident::with_dummy_span(kw::Crate);
+    let bridge = cx.ident_of("bridge", span);
+    let client = cx.ident_of("client", span);
+    let proc_macro_ty = cx.ident_of("ProcMacro", span);
+    let custom_derive = cx.ident_of("custom_derive", span);
+    let attr = cx.ident_of("attr", span);
+    let bang = cx.ident_of("bang", span);
 
     let decls = {
         let local_path = |sp: Span, name| {
-            cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![crate_kw, name]))
+            cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name]))
         };
         let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![
             proc_macro, bridge, client, proc_macro_ty, method,
         ]));
-        custom_derives.iter().map(|cd| {
-            cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![
-                cx.expr_str(cd.span, cd.trait_name),
-                cx.expr_vec_slice(
-                    span,
-                    cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
-                ),
-                local_path(cd.span, cd.function_name),
-            ])
-        }).chain(custom_attrs.iter().map(|ca| {
-            cx.expr_call(span, proc_macro_ty_method_path(attr), vec![
-                cx.expr_str(ca.span, ca.function_name.name),
-                local_path(ca.span, ca.function_name),
-            ])
-        })).chain(custom_macros.iter().map(|cm| {
-            cx.expr_call(span, proc_macro_ty_method_path(bang), vec![
-                cx.expr_str(cm.span, cm.function_name.name),
-                local_path(cm.span, cm.function_name),
-            ])
-        })).collect()
+        macros.iter().map(|m| {
+            match m {
+                ProcMacro::Derive(cd) => {
+                    cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![
+                        cx.expr_str(cd.span, cd.trait_name),
+                        cx.expr_vec_slice(
+                            span,
+                            cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
+                        ),
+                        local_path(cd.span, cd.function_name),
+                    ])
+                },
+                ProcMacro::Def(ca) => {
+                    let ident = match ca.def_type {
+                        ProcMacroDefType::Attr => attr,
+                        ProcMacroDefType::Bang => bang
+                    };
+
+                    cx.expr_call(span, proc_macro_ty_method_path(ident), vec![
+                        cx.expr_str(ca.span, ca.function_name.name),
+                        local_path(ca.span, ca.function_name),
+                    ])
+
+                }
+            }
+        }).collect()
     };
 
     let decls_static = cx.item_static(
         span,
-        Ident::from_str("_DECLS"),
+        cx.ident_of("_DECLS", span),
         cx.ty_rptr(span,
             cx.ty(span, ast::TyKind::Slice(
                 cx.ty_path(cx.path(span,
@@ -392,22 +404,22 @@
     ).map(|mut i| {
         let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
         i.attrs.push(cx.attribute(attr));
-        i.vis = respan(span, ast::VisibilityKind::Public);
         i
     });
 
-    let module = cx.item_mod(
+    let block = cx.expr_block(cx.block(
         span,
-        span,
-        ast::Ident::from_str("decls").gensym(),
-        vec![doc_hidden],
-        vec![krate, decls_static],
-    ).map(|mut i| {
-        i.vis = respan(span, ast::VisibilityKind::Public);
-        i
-    });
+        vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)],
+    ));
 
-    // Integrate the new module into existing module structures.
-    let module = AstFragment::Items(smallvec![module]);
-    cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap()
+    let anon_constant = cx.item_const(
+        span,
+        ast::Ident::new(kw::Underscore, span),
+        cx.ty(span, ast::TyKind::Tup(Vec::new())),
+        block,
+    );
+
+    // Integrate the new item into existing module structures.
+    let items = AstFragment::Items(smallvec![anon_constant]);
+    cx.monotonic_expander().fully_expand_fragment(items).make_items().pop().unwrap()
 }
diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs
index e008ed7..9dc9d66 100644
--- a/src/libsyntax_ext/source_util.rs
+++ b/src/libsyntax_ext/source_util.rs
@@ -4,7 +4,7 @@
 use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::symbol::Symbol;
-use syntax::tokenstream;
+use syntax::tokenstream::TokenStream;
 
 use smallvec::SmallVec;
 use syntax_pos::{self, Pos, Span};
@@ -16,7 +16,7 @@
 // a given file into the current one.
 
 /// line!(): expands to the current line number
-pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                    -> Box<dyn base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "line!");
 
@@ -27,7 +27,7 @@
 }
 
 /* column!(): expands to the current column number */
-pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                   -> Box<dyn base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "column!");
 
@@ -40,7 +40,7 @@
 /// file!(): expands to the current filename */
 /// The source_file (`loc.file`) contains a bunch more information we could spit
 /// out if we wanted.
-pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                    -> Box<dyn base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "file!");
 
@@ -49,13 +49,13 @@
     base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name.to_string())))
 }
 
-pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                         -> Box<dyn base::MacResult+'static> {
     let s = pprust::tts_to_string(tts);
     base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
 }
 
-pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                   -> Box<dyn base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "module_path!");
     let mod_path = &cx.current_expansion.module.mod_path;
@@ -67,7 +67,7 @@
 /// include! : parse the given file as an expr
 /// This is generally a bad idea because it's going to behave
 /// unhygienically.
-pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                            -> Box<dyn base::MacResult+'cx> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
         Some(f) => f,
@@ -105,7 +105,7 @@
 }
 
 // include_str! : read the given file, insert it as a literal string expr
-pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                           -> Box<dyn base::MacResult+'static> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
         Some(f) => f,
@@ -130,7 +130,7 @@
     }
 }
 
-pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                             -> Box<dyn base::MacResult+'static> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
         Some(f) => f,
diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs
index 8ca3763..c577b1e 100644
--- a/src/libsyntax_ext/standard_library_imports.rs
+++ b/src/libsyntax_ext/standard_library_imports.rs
@@ -1,86 +1,86 @@
 use syntax::{ast, attr};
 use syntax::edition::Edition;
-use syntax::ext::hygiene::MacroKind;
+use syntax::ext::expand::ExpansionConfig;
+use syntax::ext::hygiene::AstPass;
+use syntax::ext::base::{ExtCtxt, Resolver};
+use syntax::parse::ParseSess;
 use syntax::ptr::P;
-use syntax::source_map::{ExpnData, ExpnKind, dummy_spanned, respan};
 use syntax::symbol::{Ident, Symbol, kw, sym};
 use syntax_pos::DUMMY_SP;
 
-use std::iter;
-
 pub fn inject(
-    mut krate: ast::Crate, alt_std_name: Option<&str>, edition: Edition
+    mut krate: ast::Crate,
+    resolver: &mut dyn Resolver,
+    sess: &ParseSess,
+    alt_std_name: Option<Symbol>,
 ) -> (ast::Crate, Option<Symbol>) {
-    let rust_2018 = edition >= Edition::Edition2018;
+    let rust_2018 = sess.edition >= Edition::Edition2018;
 
     // the first name in this list is the crate name of the crate with the prelude
-    let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) {
+    let names: &[Symbol] = if attr::contains_name(&krate.attrs, sym::no_core) {
         return (krate, None);
     } else if attr::contains_name(&krate.attrs, sym::no_std) {
         if attr::contains_name(&krate.attrs, sym::compiler_builtins) {
-            &["core"]
+            &[sym::core]
         } else {
-            &["core", "compiler_builtins"]
+            &[sym::core, sym::compiler_builtins]
         }
     } else {
-        &["std"]
+        &[sym::std]
     };
 
+    let expn_id = resolver.expansion_for_ast_pass(
+        DUMMY_SP,
+        AstPass::StdImports,
+        &[sym::prelude_import],
+        None,
+    );
+    let span = DUMMY_SP.with_def_site_ctxt(expn_id);
+    let call_site = DUMMY_SP.with_call_site_ctxt(expn_id);
+
+    let ecfg = ExpansionConfig::default("std_lib_injection".to_string());
+    let cx = ExtCtxt::new(sess, ecfg, resolver);
+
+
     // .rev() to preserve ordering above in combination with insert(0, ...)
-    let alt_std_name = alt_std_name.map(Symbol::intern);
-    for orig_name_str in names.iter().rev() {
-        // HACK(eddyb) gensym the injected crates on the Rust 2018 edition,
-        // so they don't accidentally interfere with the new import paths.
-        let orig_name_sym = Symbol::intern(orig_name_str);
-        let orig_name_ident = Ident::with_dummy_span(orig_name_sym);
-        let (rename, orig_name) = if rust_2018 {
-            (orig_name_ident.gensym(), Some(orig_name_sym))
+    for &name in names.iter().rev() {
+        let ident = if rust_2018 {
+            Ident::new(name, span)
         } else {
-            (orig_name_ident, None)
+            Ident::new(name, call_site)
         };
-        krate.module.items.insert(0, P(ast::Item {
-            attrs: vec![attr::mk_attr_outer(
-                attr::mk_word_item(ast::Ident::with_dummy_span(sym::macro_use))
-            )],
-            vis: dummy_spanned(ast::VisibilityKind::Inherited),
-            node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)),
-            ident: rename,
-            id: ast::DUMMY_NODE_ID,
-            span: DUMMY_SP,
-            tokens: None,
-        }));
+        krate.module.items.insert(0, cx.item(
+            span,
+            ident,
+            vec![cx.attribute(cx.meta_word(span, sym::macro_use))],
+            ast::ItemKind::ExternCrate(alt_std_name),
+        ));
     }
 
-    // the crates have been injected, the assumption is that the first one is the one with
-    // the prelude.
+    // The crates have been injected, the assumption is that the first one is
+    // the one with the prelude.
     let name = names[0];
 
-    let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
-        ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition,
-        [sym::prelude_import][..].into(),
-    ));
+    let import_path = if rust_2018 {
+        [name, sym::prelude, sym::v1].iter()
+            .map(|symbol| ast::Ident::new(*symbol, span)).collect()
+    } else {
+        [kw::PathRoot, name, sym::prelude, sym::v1].iter()
+            .map(|symbol| ast::Ident::new(*symbol, span)).collect()
+    };
 
-    krate.module.items.insert(0, P(ast::Item {
-        attrs: vec![attr::mk_attr_outer(
-            attr::mk_word_item(ast::Ident::new(sym::prelude_import, span)))],
-        vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
-        node: ast::ItemKind::Use(P(ast::UseTree {
-            prefix: ast::Path {
-                segments: iter::once(ast::Ident::with_dummy_span(kw::PathRoot))
-                    .chain(
-                        [name, "prelude", "v1"].iter().cloned()
-                            .map(ast::Ident::from_str)
-                    ).map(ast::PathSegment::from_ident).collect(),
-                span,
-            },
+    let use_item = cx.item(
+        span,
+        ast::Ident::invalid(),
+        vec![cx.attribute(cx.meta_word(span, sym::prelude_import))],
+        ast::ItemKind::Use(P(ast::UseTree {
+            prefix: cx.path(span, import_path),
             kind: ast::UseTreeKind::Glob,
             span,
         })),
-        id: ast::DUMMY_NODE_ID,
-        ident: ast::Ident::invalid(),
-        span,
-        tokens: None,
-    }));
+    );
 
-    (krate, Some(Symbol::intern(name)))
+    krate.module.items.insert(0, use_item);
+
+    (krate, Some(name))
 }
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index 5fd87d3..0910c00 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -28,11 +28,11 @@
 
     if !ecx.ecfg.should_test { return vec![]; }
 
-    let sp = ecx.with_legacy_ctxt(attr_sp);
+    let sp = ecx.with_def_site_ctxt(attr_sp);
     let mut item = anno_item.expect_item();
     item = item.map(|mut item| {
         item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
-        item.ident = item.ident.gensym();
+        item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
         item.attrs.push(
             ecx.attribute(ecx.meta_word(sp, sym::rustc_test_marker))
         );
@@ -92,27 +92,26 @@
         return vec![Annotatable::Item(item)];
     }
 
-    let (sp, attr_sp) = (cx.with_legacy_ctxt(item.span), cx.with_legacy_ctxt(attr_sp));
+    let (sp, attr_sp) = (cx.with_def_site_ctxt(item.span), cx.with_def_site_ctxt(attr_sp));
 
-    // Gensym "test" so we can extern crate without conflicting with any local names
-    let test_id = cx.ident_of("test").gensym();
+    let test_id = ast::Ident::new(sym::test, attr_sp);
 
     // creates test::$name
     let test_path = |name| {
-        cx.path(sp, vec![test_id, cx.ident_of(name)])
+        cx.path(sp, vec![test_id, cx.ident_of(name, sp)])
     };
 
     // creates test::ShouldPanic::$name
     let should_panic_path = |name| {
-        cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic"), cx.ident_of(name)])
+        cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic", sp), cx.ident_of(name, sp)])
     };
 
     // creates $name: $expr
-    let field = |name, expr| cx.field_imm(sp, cx.ident_of(name), expr);
+    let field = |name, expr| cx.field_imm(sp, cx.ident_of(name, sp), expr);
 
     let test_fn = if is_bench {
         // A simple ident for a lambda
-        let b = cx.ident_of("b");
+        let b = cx.ident_of("b", attr_sp);
 
         cx.expr_call(sp, cx.expr_path(test_path("StaticBenchFn")), vec![
             // |b| self::test::assert_test_result(
@@ -143,7 +142,7 @@
         ])
     };
 
-    let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name, sp).gensym(),
+    let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name, sp),
         vec![
             // #[cfg(test)]
             cx.attribute(cx.meta_list(attr_sp, sym::cfg, vec![
@@ -192,17 +191,17 @@
         ));
     test_const = test_const.map(|mut tc| { tc.vis.node = ast::VisibilityKind::Public; tc});
 
-    // extern crate test as test_gensym
+    // extern crate test
     let test_extern = cx.item(sp,
         test_id,
         vec![],
-        ast::ItemKind::ExternCrate(Some(sym::test))
+        ast::ItemKind::ExternCrate(None)
     );
 
     log::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
     vec![
-        // Access to libtest under a gensymed name
+        // Access to libtest under a hygienic name
         Annotatable::Item(test_extern),
         // The generated test case
         Annotatable::Item(test_const),
diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs
index 4a6ea0e..56de0c9 100644
--- a/src/libsyntax_ext/test_harness.rs
+++ b/src/libsyntax_ext/test_harness.rs
@@ -5,32 +5,30 @@
 use syntax::ast::{self, Ident};
 use syntax::attr;
 use syntax::entry::{self, EntryPointType};
-use syntax::ext::base::{ExtCtxt, MacroKind, Resolver};
+use syntax::ext::base::{ExtCtxt, Resolver};
 use syntax::ext::expand::{AstFragment, ExpansionConfig};
 use syntax::feature_gate::Features;
 use syntax::mut_visit::{*, ExpectOne};
 use syntax::parse::ParseSess;
 use syntax::ptr::P;
-use syntax::source_map::{ExpnData, ExpnKind, dummy_spanned};
-use syntax::symbol::{kw, sym, Symbol};
+use syntax::source_map::respan;
+use syntax::symbol::{sym, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::hygiene::{AstPass, SyntaxContext, Transparency};
 
 use std::{iter, mem};
 
 struct Test {
     span: Span,
-    path: Vec<Ident>,
+    ident: Ident,
 }
 
 struct TestCtxt<'a> {
-    span_diagnostic: &'a errors::Handler,
-    path: Vec<Ident>,
     ext_cx: ExtCtxt<'a>,
+    def_site: Span,
     test_cases: Vec<Test>,
     reexport_test_harness_main: Option<Symbol>,
     test_runner: Option<ast::Path>,
-    // top-level re-export submodule, filled out after folding is finished
-    toplevel_reexport: Option<Ident>,
 }
 
 // Traverse the crate, collecting all the test functions, eliding any
@@ -43,8 +41,8 @@
     span_diagnostic: &errors::Handler,
     features: &Features,
 ) {
-    // Check for #[reexport_test_harness_main = "some_name"] which
-    // creates a `use __test::main as some_name;`. This needs to be
+    // Check for #![reexport_test_harness_main = "some_name"] which gives the
+    // main test function the name `some_name` without hygiene. This needs to be
     // unconditional, so that the attribute is still marked as used in
     // non-test builds.
     let reexport_test_harness_main =
@@ -56,16 +54,13 @@
 
     if should_test {
         generate_test_harness(sess, resolver, reexport_test_harness_main,
-                              krate, span_diagnostic, features, test_runner)
+                              krate, features, test_runner)
     }
 }
 
 struct TestHarnessGenerator<'a> {
     cx: TestCtxt<'a>,
-    tests: Vec<Ident>,
-
-    // submodule name, gensym'd identifier for re-exports
-    tested_submods: Vec<(Ident, Ident)>,
+    tests: Vec<Test>,
 }
 
 impl<'a> MutVisitor for TestHarnessGenerator<'a> {
@@ -77,49 +72,47 @@
     }
 
     fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
-        let ident = i.ident;
-        if ident.name != kw::Invalid {
-            self.cx.path.push(ident);
-        }
-        debug!("current path: {}", path_name_i(&self.cx.path));
-
         let mut item = i.into_inner();
         if is_test_case(&item) {
             debug!("this is a test item");
 
             let test = Test {
                 span: item.span,
-                path: self.cx.path.clone(),
+                ident: item.ident,
             };
-            self.cx.test_cases.push(test);
-            self.tests.push(item.ident);
+            self.tests.push(test);
         }
 
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
         if let ast::ItemKind::Mod(mut module) = item.node {
             let tests = mem::take(&mut self.tests);
-            let tested_submods = mem::take(&mut self.tested_submods);
             noop_visit_mod(&mut module, self);
-            let tests = mem::replace(&mut self.tests, tests);
-            let tested_submods = mem::replace(&mut self.tested_submods, tested_submods);
+            let mut tests = mem::replace(&mut self.tests, tests);
 
-            if !tests.is_empty() || !tested_submods.is_empty() {
-                let (it, sym) = mk_reexport_mod(&mut self.cx, item.id, tests, tested_submods);
-                module.items.push(it);
-
-                if !self.cx.path.is_empty() {
-                    self.tested_submods.push((self.cx.path[self.cx.path.len()-1], sym));
+            if !tests.is_empty() {
+                let parent = if item.id == ast::DUMMY_NODE_ID {
+                    ast::CRATE_NODE_ID
                 } else {
-                    debug!("pushing nothing, sym: {:?}", sym);
-                    self.cx.toplevel_reexport = Some(sym);
+                    item.id
+                };
+                // Create an identifier that will hygienically resolve the test
+                // case name, even in another module.
+                let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
+                    module.inner,
+                    AstPass::TestHarness,
+                    &[],
+                    Some(parent),
+                );
+                for test in &mut tests {
+                    // See the comment on `mk_main` for why we're using
+                    // `apply_mark` directly.
+                    test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque);
                 }
+                self.cx.test_cases.extend(tests);
             }
             item.node = ast::ItemKind::Mod(module);
         }
-        if ident.name != kw::Invalid {
-            self.cx.path.pop();
-        }
         smallvec![P(item)]
     }
 
@@ -133,6 +126,7 @@
 struct EntryPointCleaner {
     // Current depth in the ast
     depth: usize,
+    def_site: Span,
 }
 
 impl MutVisitor for EntryPointCleaner {
@@ -149,8 +143,10 @@
             EntryPointType::MainAttr |
             EntryPointType::Start =>
                 item.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| {
-                    let allow_ident = Ident::with_dummy_span(sym::allow);
-                    let dc_nested = attr::mk_nested_word_item(Ident::from_str("dead_code"));
+                    let allow_ident = Ident::new(sym::allow, self.def_site);
+                    let dc_nested = attr::mk_nested_word_item(
+                        Ident::from_str_and_span("dead_code", self.def_site),
+                    );
                     let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]);
                     let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item);
 
@@ -181,124 +177,99 @@
     }
 }
 
-/// Creates an item (specifically a module) that "pub use"s the tests passed in.
-/// Each tested submodule will contain a similar reexport module that we will export
-/// under the name of the original module. That is, `submod::__test_reexports` is
-/// reexported like so `pub use submod::__test_reexports as submod`.
-fn mk_reexport_mod(cx: &mut TestCtxt<'_>,
-                   parent: ast::NodeId,
-                   tests: Vec<Ident>,
-                   tested_submods: Vec<(Ident, Ident)>)
-                   -> (P<ast::Item>, Ident) {
-    let super_ = Ident::with_dummy_span(kw::Super);
-
-    let items = tests.into_iter().map(|r| {
-        cx.ext_cx.item_use_simple(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
-                                  cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
-    }).chain(tested_submods.into_iter().map(|(r, sym)| {
-        let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
-        cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
-                                   Some(r), path)
-    })).collect();
-
-    let reexport_mod = ast::Mod {
-        inline: true,
-        inner: DUMMY_SP,
-        items,
-    };
-
-    let name = Ident::from_str("__test_reexports").gensym();
-    let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent };
-    cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent);
-    let module = P(ast::Item {
-        ident: name,
-        attrs: Vec::new(),
-        id: ast::DUMMY_NODE_ID,
-        node: ast::ItemKind::Mod(reexport_mod),
-        vis: dummy_spanned(ast::VisibilityKind::Public),
-        span: DUMMY_SP,
-        tokens: None,
-    });
-
-    // Integrate the new module into existing module structures.
-    let module = AstFragment::Items(smallvec![module]);
-    let module =
-        cx.ext_cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap();
-
-    (module, name)
-}
-
 /// Crawl over the crate, inserting test reexports and the test main function
 fn generate_test_harness(sess: &ParseSess,
                          resolver: &mut dyn Resolver,
                          reexport_test_harness_main: Option<Symbol>,
                          krate: &mut ast::Crate,
-                         sd: &errors::Handler,
                          features: &Features,
                          test_runner: Option<ast::Path>) {
-    // Remove the entry points
-    let mut cleaner = EntryPointCleaner { depth: 0 };
-    cleaner.visit_crate(krate);
-
     let mut econfig = ExpansionConfig::default("test".to_string());
     econfig.features = Some(features);
 
+    let ext_cx = ExtCtxt::new(sess, econfig, resolver);
+
+    let expn_id = ext_cx.resolver.expansion_for_ast_pass(
+        DUMMY_SP,
+        AstPass::TestHarness,
+        &[sym::main, sym::test, sym::rustc_attrs],
+        None,
+    );
+    let def_site = DUMMY_SP.with_def_site_ctxt(expn_id);
+
+    // Remove the entry points
+    let mut cleaner = EntryPointCleaner { depth: 0, def_site };
+    cleaner.visit_crate(krate);
+
     let cx = TestCtxt {
-        span_diagnostic: sd,
-        ext_cx: ExtCtxt::new(sess, econfig, resolver),
-        path: Vec::new(),
+        ext_cx,
+        def_site,
         test_cases: Vec::new(),
         reexport_test_harness_main,
-        toplevel_reexport: None,
         test_runner
     };
 
     TestHarnessGenerator {
         cx,
         tests: Vec::new(),
-        tested_submods: Vec::new(),
     }.visit_crate(krate);
 }
 
 /// Creates a function item for use as the main function of a test build.
 /// This function will call the `test_runner` as specified by the crate attribute
+///
+/// By default this expands to
+///
+/// #[main]
+/// pub fn main() {
+///     extern crate test;
+///     test::test_main_static(&[
+///         &test_const1,
+///         &test_const2,
+///         &test_const3,
+///     ]);
+/// }
+///
+/// Most of the Ident have the usual def-site hygiene for the AST pass. The
+/// exception is the `test_const`s. These have a syntax context that has two
+/// opaque marks: one from the expansion of `test` or `test_case`, and one
+/// generated  in `TestHarnessGenerator::flat_map_item`. When resolving this
+/// identifier after failing to find a matching identifier in the root module
+/// we remove the outer mark, and try resolving at its def-site, which will
+/// then resolve to `test_const`.
+///
+/// The expansion here can be controlled by two attributes:
+///
+/// `reexport_test_harness_main` provides a different name for the `main`
+/// function and `test_runner` provides a path that replaces
+/// `test::test_main_static`.
 fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
-    // Writing this out by hand:
-    //        pub fn main() {
-    //            #![main]
-    //            test::test_main_static(&[..tests]);
-    //        }
-    let sp = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
-        ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, cx.ext_cx.parse_sess.edition,
-        [sym::main, sym::test, sym::rustc_attrs][..].into(),
-    ));
+    let sp = cx.def_site;
     let ecx = &cx.ext_cx;
-    let test_id = Ident::with_dummy_span(sym::test);
+    let test_id = Ident::new(sym::test, sp);
 
     // test::test_main_static(...)
     let mut test_runner = cx.test_runner.clone().unwrap_or(
-        ecx.path(sp, vec![
-            test_id, ecx.ident_of("test_main_static")
-        ]));
+        ecx.path(sp, vec![test_id, ecx.ident_of("test_main_static", sp)]));
 
     test_runner.span = sp;
 
     let test_main_path_expr = ecx.expr_path(test_runner);
     let call_test_main = ecx.expr_call(sp, test_main_path_expr,
-                                       vec![mk_tests_slice(cx)]);
+                                       vec![mk_tests_slice(cx, sp)]);
     let call_test_main = ecx.stmt_expr(call_test_main);
 
-    // #![main]
-    let main_meta = ecx.meta_word(sp, sym::main);
-    let main_attr = ecx.attribute(main_meta);
-
-    // extern crate test as test_gensym
+    // extern crate test
     let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp,
         test_id,
         vec![],
         ast::ItemKind::ExternCrate(None)
     ));
 
+    // #[main]
+    let main_meta = ecx.meta_word(sp, sym::main);
+    let main_attr = ecx.attribute(main_meta);
+
     // pub fn main() { ... }
     let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
 
@@ -316,8 +287,8 @@
 
     // Honor the reexport_test_harness_main attribute
     let main_id = match cx.reexport_test_harness_main {
-        Some(sym) => Ident::new(sym, sp),
-        None => Ident::from_str_and_span("main", sp).gensym(),
+        Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
+        None => Ident::new(sym::main, sp),
     };
 
     let main = P(ast::Item {
@@ -325,7 +296,7 @@
         attrs: vec![main_attr],
         id: ast::DUMMY_NODE_ID,
         node: main,
-        vis: dummy_spanned(ast::VisibilityKind::Public),
+        vis: respan(sp, ast::VisibilityKind::Public),
         span: sp,
         tokens: None,
     });
@@ -335,44 +306,20 @@
     cx.ext_cx.monotonic_expander().fully_expand_fragment(main).make_items().pop().unwrap()
 }
 
-fn path_name_i(idents: &[Ident]) -> String {
-    let mut path_name = "".to_string();
-    let mut idents_iter = idents.iter().peekable();
-    while let Some(ident) = idents_iter.next() {
-        path_name.push_str(&ident.as_str());
-        if idents_iter.peek().is_some() {
-            path_name.push_str("::")
-        }
-    }
-    path_name
-}
-
 /// Creates a slice containing every test like so:
-/// &[path::to::test1, path::to::test2]
-fn mk_tests_slice(cx: &TestCtxt<'_>) -> P<ast::Expr> {
+/// &[&test1, &test2]
+fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
     debug!("building test vector from {} tests", cx.test_cases.len());
     let ref ecx = cx.ext_cx;
 
-    ecx.expr_vec_slice(DUMMY_SP,
+
+    ecx.expr_vec_slice(sp,
         cx.test_cases.iter().map(|test| {
             ecx.expr_addr_of(test.span,
-                ecx.expr_path(ecx.path(test.span, visible_path(cx, &test.path))))
+                ecx.expr_path(ecx.path(test.span, vec![test.ident])))
         }).collect())
 }
 
-/// Creates a path from the top-level __test module to the test via __test_reexports
-fn visible_path(cx: &TestCtxt<'_>, path: &[Ident]) -> Vec<Ident>{
-    let mut visible_path = vec![];
-    match cx.toplevel_reexport {
-        Some(id) => visible_path.push(id),
-        None => {
-            cx.span_diagnostic.bug("expected to find top-level re-export name, but found None");
-        }
-    }
-    visible_path.extend_from_slice(path);
-    visible_path
-}
-
 fn is_test_case(i: &ast::Item) -> bool {
     attr::contains_name(&i.attrs, sym::rustc_test_marker)
 }
diff --git a/src/libsyntax_ext/trace_macros.rs b/src/libsyntax_ext/trace_macros.rs
index 0dce8a3..d83c240 100644
--- a/src/libsyntax_ext/trace_macros.rs
+++ b/src/libsyntax_ext/trace_macros.rs
@@ -1,20 +1,27 @@
 use syntax::ext::base::{self, ExtCtxt};
 use syntax::symbol::kw;
 use syntax_pos::Span;
-use syntax::tokenstream::TokenTree;
+use syntax::tokenstream::{TokenTree, TokenStream};
 
 pub fn expand_trace_macros(cx: &mut ExtCtxt<'_>,
                            sp: Span,
-                           tt: &[TokenTree])
+                           tt: TokenStream)
                            -> Box<dyn base::MacResult + 'static> {
-    match tt {
-        [TokenTree::Token(token)] if token.is_keyword(kw::True) => {
-            cx.set_trace_macros(true);
-        }
-        [TokenTree::Token(token)] if token.is_keyword(kw::False) => {
-            cx.set_trace_macros(false);
-        }
-        _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
+    let mut cursor = tt.into_trees();
+    let mut err = false;
+    let value = match &cursor.next() {
+        Some(TokenTree::Token(token)) if token.is_keyword(kw::True) => true,
+        Some(TokenTree::Token(token)) if token.is_keyword(kw::False) => false,
+        _ => {
+            err = true;
+            false
+        },
+    };
+    err |= cursor.next().is_some();
+    if err {
+        cx.span_err(sp, "trace_macros! accepts only `true` or `false`")
+    } else {
+        cx.set_trace_macros(value);
     }
 
     base::DummyResult::any_valid(sp)
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 733f6f0..e28d932 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -343,6 +343,38 @@
     }))
 }
 
+pub fn debug_hygiene_data(verbose: bool) -> String {
+    HygieneData::with(|data| {
+        if verbose {
+            format!("{:#?}", data)
+        } else {
+            let mut s = String::from("");
+            s.push_str("Expansions:");
+            data.expn_data.iter().enumerate().for_each(|(id, expn_info)| {
+                let expn_info = expn_info.as_ref().expect("no expansion data for an expansion ID");
+                s.push_str(&format!(
+                    "\n{}: parent: {:?}, call_site_ctxt: {:?}, kind: {:?}",
+                    id,
+                    expn_info.parent,
+                    expn_info.call_site.ctxt(),
+                    expn_info.kind,
+                ));
+            });
+            s.push_str("\n\nSyntaxContexts:");
+            data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| {
+                s.push_str(&format!(
+                    "\n#{}: parent: {:?}, outer_mark: ({:?}, {:?})",
+                    id,
+                    ctxt.parent,
+                    ctxt.outer_expn,
+                    ctxt.outer_transparency,
+                ));
+            });
+            s
+        }
+    })
+}
+
 impl SyntaxContext {
     #[inline]
     pub const fn root() -> Self {
@@ -360,7 +392,7 @@
     }
 
     /// Extend a syntax context with a given expansion and transparency.
-    pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
+    crate fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
         HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
     }
 
@@ -550,7 +582,7 @@
     /// The returned span belongs to the created expansion and has the new properties,
     /// but its location is inherited from the current span.
     pub fn fresh_expansion(self, expn_data: ExpnData) -> Span {
-        self.fresh_expansion_with_transparency(expn_data, Transparency::SemiTransparent)
+        self.fresh_expansion_with_transparency(expn_data, Transparency::Transparent)
     }
 
     pub fn fresh_expansion_with_transparency(
@@ -639,8 +671,9 @@
     /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind.
     Root,
     /// Expansion produced by a macro.
-    /// FIXME: Some code injected by the compiler before HIR lowering also gets this kind.
     Macro(MacroKind, Symbol),
+    /// Transform done by the compiler on the AST.
+    AstPass(AstPass),
     /// Desugaring done by the compiler during HIR lowering.
     Desugaring(DesugaringKind)
 }
@@ -650,6 +683,7 @@
         match *self {
             ExpnKind::Root => kw::PathRoot,
             ExpnKind::Macro(_, descr) => descr,
+            ExpnKind::AstPass(kind) => Symbol::intern(kind.descr()),
             ExpnKind::Desugaring(kind) => Symbol::intern(kind.descr()),
         }
     }
@@ -675,6 +709,13 @@
         }
     }
 
+    pub fn descr_expected(self) -> &'static str {
+        match self {
+            MacroKind::Attr => "attribute",
+            _ => self.descr(),
+        }
+    }
+
     pub fn article(self) -> &'static str {
         match self {
             MacroKind::Attr => "an",
@@ -683,6 +724,26 @@
     }
 }
 
+/// The kind of AST transform.
+#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+pub enum AstPass {
+    StdImports,
+    TestHarness,
+    ProcMacroHarness,
+    PluginMacroDefs,
+}
+
+impl AstPass {
+    fn descr(self) -> &'static str {
+        match self {
+            AstPass::StdImports => "standard library imports",
+            AstPass::TestHarness => "test harness",
+            AstPass::ProcMacroHarness => "proc macro harness",
+            AstPass::PluginMacroDefs => "plugin macro definitions",
+        }
+    }
+}
+
 /// The kind of compiler desugaring.
 #[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)]
 pub enum DesugaringKind {
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 3d8bfc7..ca177eb 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -442,6 +442,7 @@
                 let (pre, post) = match expn_data.kind {
                     ExpnKind::Root => break,
                     ExpnKind::Desugaring(..) => ("desugaring of ", ""),
+                    ExpnKind::AstPass(..) => ("", ""),
                     ExpnKind::Macro(macro_kind, _) => match macro_kind {
                         MacroKind::Bang => ("", "!"),
                         MacroKind::Attr => ("#[", "]"),
@@ -513,6 +514,18 @@
                   span.ctxt)
     }
 
+    /// Equivalent of `Span::def_site` from the proc macro API,
+    /// except that the location is taken from the `self` span.
+    pub fn with_def_site_ctxt(self, expn_id: ExpnId) -> Span {
+        self.with_ctxt_from_mark(expn_id, Transparency::Opaque)
+    }
+
+    /// Equivalent of `Span::call_site` from the proc macro API,
+    /// except that the location is taken from the `self` span.
+    pub fn with_call_site_ctxt(&self, expn_id: ExpnId) -> Span {
+        self.with_ctxt_from_mark(expn_id, Transparency::Transparent)
+    }
+
     /// Produces a span with the same location as `self` and context produced by a macro with the
     /// given ID and transparency, assuming that macro was defined directly and not produced by
     /// some other macro (which is the case for built-in and procedural macros).
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index f44716e..597ae83 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -626,6 +626,7 @@
         size,
         slice_patterns,
         slicing_syntax,
+        soft,
         Some,
         specialization,
         speed,
@@ -764,7 +765,7 @@
         Ident::with_dummy_span(string.as_symbol())
     }
 
-    /// Maps a string to an identifier with an empty span.
+    /// Maps a string to an identifier with a dummy span.
     pub fn from_str(string: &str) -> Ident {
         Ident::with_dummy_span(Symbol::intern(string))
     }
@@ -801,27 +802,25 @@
         Ident::new(self.name, self.span.modern_and_legacy())
     }
 
-    /// Transforms an identifier into one with the same name, but gensymed.
-    pub fn gensym(self) -> Ident {
-        let name = with_interner(|interner| interner.gensymed(self.name));
-        Ident::new(name, self.span)
-    }
-
     /// Transforms an underscore identifier into one with the same name, but
     /// gensymed. Leaves non-underscore identifiers unchanged.
     pub fn gensym_if_underscore(self) -> Ident {
-        if self.name == kw::Underscore { self.gensym() } else { self }
+        if self.name == kw::Underscore {
+            let name = with_interner(|interner| interner.gensymed(self.name));
+            Ident::new(name, self.span)
+        } else {
+            self
+        }
     }
 
-    // WARNING: this function is deprecated and will be removed in the future.
-    pub fn is_gensymed(self) -> bool {
-        with_interner(|interner| interner.is_gensymed(self.name))
-    }
-
+    /// Convert the name to a `LocalInternedString`. This is a slowish
+    /// operation because it requires locking the symbol interner.
     pub fn as_str(self) -> LocalInternedString {
         self.name.as_str()
     }
 
+    /// Convert the name to an `InternedString`. This is a slowish operation
+    /// because it requires locking the symbol interner.
     pub fn as_interned_str(self) -> InternedString {
         self.name.as_interned_str()
     }
@@ -888,9 +887,12 @@
 ///
 /// Examples:
 /// ```
-/// assert_eq!(Ident::from_str("x"), Ident::from_str("x"))
-/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x"))
-/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x").gensym())
+/// assert_eq!(Ident::from_str("_"), Ident::from_str("_"))
+/// assert_ne!(Ident::from_str("_").gensym_if_underscore(), Ident::from_str("_"))
+/// assert_ne!(
+///     Ident::from_str("_").gensym_if_underscore(),
+///     Ident::from_str("_").gensym_if_underscore(),
+/// )
 /// ```
 /// Internally, a symbol is implemented as an index, and all operations
 /// (including hashing, equality, and ordering) operate on that index. The use
@@ -916,6 +918,25 @@
         with_interner(|interner| interner.intern(string))
     }
 
+    /// Access the symbol's chars. This is a slowish operation because it
+    /// requires locking the symbol interner.
+    pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
+        with_interner(|interner| {
+            f(interner.get(self))
+        })
+    }
+
+    /// Access two symbols' chars. This is a slowish operation because it
+    /// requires locking the symbol interner, but it is faster than calling
+    /// `with()` twice.
+    fn with2<F: FnOnce(&str, &str) -> R, R>(self, other: Symbol, f: F) -> R {
+        with_interner(|interner| {
+            f(interner.get(self), interner.get(other))
+        })
+    }
+
+    /// Convert to a `LocalInternedString`. This is a slowish operation because
+    /// it requires locking the symbol interner.
     pub fn as_str(self) -> LocalInternedString {
         with_interner(|interner| unsafe {
             LocalInternedString {
@@ -924,6 +945,8 @@
         })
     }
 
+    /// Convert to an `InternedString`. This is a slowish operation because it
+    /// requires locking the symbol interner.
     pub fn as_interned_str(self) -> InternedString {
         with_interner(|interner| InternedString {
             symbol: interner.interned(self)
@@ -1152,39 +1175,11 @@
 // FIXME: ensure that the interner outlives any thread which uses
 // `LocalInternedString`, by creating a new thread right after constructing the
 // interner.
-#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
+#[derive(Clone, Copy, Eq, PartialOrd, Ord)]
 pub struct LocalInternedString {
     string: &'static str,
 }
 
-impl LocalInternedString {
-    /// Maps a string to its interned representation.
-    pub fn intern(string: &str) -> Self {
-        let string = with_interner(|interner| {
-            let symbol = interner.intern(string);
-            interner.strings[symbol.0.as_usize()]
-        });
-        LocalInternedString {
-            string: unsafe { std::mem::transmute::<&str, &str>(string) }
-        }
-    }
-
-    pub fn as_interned_str(self) -> InternedString {
-        InternedString {
-            symbol: Symbol::intern(self.string)
-        }
-    }
-
-    #[inline]
-    pub fn get(&self) -> &str {
-        // This returns a valid string since we ensure that `self` outlives the interner
-        // by creating the interner on a thread which outlives threads which can access it.
-        // This type cannot move to a thread which outlives the interner since it does
-        // not implement Send.
-        self.string
-    }
-}
-
 impl<U: ?Sized> std::convert::AsRef<U> for LocalInternedString
 where
     str: std::convert::AsRef<U>
@@ -1246,18 +1241,6 @@
     }
 }
 
-impl Decodable for LocalInternedString {
-    fn decode<D: Decoder>(d: &mut D) -> Result<LocalInternedString, D::Error> {
-        Ok(LocalInternedString::intern(&d.read_str()?))
-    }
-}
-
-impl Encodable for LocalInternedString {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(self.string)
-    }
-}
-
 /// An alternative to `Symbol` that is focused on string contents. It has two
 /// main differences to `Symbol`.
 ///
@@ -1285,28 +1268,19 @@
     }
 
     pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
-        let str = with_interner(|interner| {
-            interner.get(self.symbol) as *const str
-        });
-        // This is safe because the interner keeps string alive until it is dropped.
-        // We can access it because we know the interner is still alive since we use a
-        // scoped thread local to access it, and it was alive at the beginning of this scope
-        unsafe { f(&*str) }
+        self.symbol.with(f)
     }
 
     fn with2<F: FnOnce(&str, &str) -> R, R>(self, other: &InternedString, f: F) -> R {
-        let (self_str, other_str) = with_interner(|interner| {
-            (interner.get(self.symbol) as *const str,
-             interner.get(other.symbol) as *const str)
-        });
-        // This is safe for the same reason that `with` is safe.
-        unsafe { f(&*self_str, &*other_str) }
+        self.symbol.with2(other.symbol, f)
     }
 
     pub fn as_symbol(self) -> Symbol {
         self.symbol
     }
 
+    /// Convert to a `LocalInternedString`. This is a slowish operation because it
+    /// requires locking the symbol interner.
     pub fn as_str(self) -> LocalInternedString {
         self.symbol.as_str()
     }
diff --git a/src/llvm-project b/src/llvm-project
index 48818e9..71fe7ec 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 48818e9f5d0f2d5978a9b43ad1a2e8d0b83f6aa0
+Subproject commit 71fe7ec06b85f612fc0e4eb4134c7a7d0f23fac5
diff --git a/src/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs
index ae2ff99..ded310d 100644
--- a/src/test/codegen/adjustments.rs
+++ b/src/test/codegen/adjustments.rs
@@ -3,7 +3,7 @@
 #![crate_type = "lib"]
 
 // Hack to get the correct size for the length part in slices
-// CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
+// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
 #[no_mangle]
 pub fn helper(_: usize) {
 }
diff --git a/src/test/codegen/c-variadic.rs b/src/test/codegen/c-variadic.rs
index bb90a96..2acf95d 100644
--- a/src/test/codegen/c-variadic.rs
+++ b/src/test/codegen/c-variadic.rs
@@ -1,4 +1,5 @@
 // compile-flags: -C no-prepopulate-passes
+// ignore-tidy-linelength
 
 #![crate_type = "lib"]
 #![feature(c_variadic)]
@@ -14,13 +15,13 @@
 #[unwind(aborts)] // FIXME(#58794)
 pub unsafe extern "C" fn use_foreign_c_variadic_0() {
     // Ensure that we correctly call foreign C-variadic functions.
-    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0)
+    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM:i32( signext)?]] 0)
     foreign_c_variadic_0(0);
-    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42)
+    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42)
     foreign_c_variadic_0(0, 42i32);
-    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42, i32 1024)
+    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
     foreign_c_variadic_0(0, 42i32, 1024i32);
-    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0, i32 42, i32 1024, i32 0)
+    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
     foreign_c_variadic_0(0, 42i32, 1024i32, 0i32);
 }
 
@@ -34,18 +35,18 @@
 
 #[unwind(aborts)] // FIXME(#58794)
 pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) {
-    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 42)
+    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 42)
     foreign_c_variadic_1(ap, 42i32);
 }
 #[unwind(aborts)] // FIXME(#58794)
 pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) {
-    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42)
+    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42)
     foreign_c_variadic_1(ap, 2i32, 42i32);
 }
 
 #[unwind(aborts)] // FIXME(#58794)
 pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) {
-    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42, i32 0)
+    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42, [[PARAM]] 0)
     foreign_c_variadic_1(ap, 2i32, 42i32, 0i32);
 }
 
@@ -64,12 +65,12 @@
 // Ensure that we generate the correct `call` signature when calling a Rust
 // defined C-variadic.
 pub unsafe fn test_c_variadic_call() {
-    // CHECK: call i32 (i32, ...) @c_variadic(i32 0)
+    // CHECK: call [[RET:(signext )?i32]] (i32, ...) @c_variadic([[PARAM]] 0)
     c_variadic(0);
-    // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42)
+    // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42)
     c_variadic(0, 42i32);
-    // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42, i32 1024)
+    // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
     c_variadic(0, 42i32, 1024i32);
-    // CHECK: call i32 (i32, ...) @c_variadic(i32 0, i32 42, i32 1024, i32 0)
+    // CHECK: call [[RET]] (i32, ...) @c_variadic([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
     c_variadic(0, 42i32, 1024i32, 0i32);
 }
diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs
index e152e6e..f67487c 100644
--- a/src/test/codegen/fastcall-inreg.rs
+++ b/src/test/codegen/fastcall-inreg.rs
@@ -49,27 +49,27 @@
 #![crate_type = "lib"]
 
 pub mod tests {
-    // CHECK: @f1(i32 inreg %arg0, i32 inreg %arg1, i32 %arg2)
+    // CHECK: @f1(i32 inreg %_1, i32 inreg %_2, i32 %_3)
     #[no_mangle]
     pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
 
-    // CHECK: @f2(i32* inreg %arg0, i32* inreg %arg1, i32* %arg2)
+    // CHECK: @f2(i32* inreg %_1, i32* inreg %_2, i32* %_3)
     #[no_mangle]
     pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}
 
-    // CHECK: @f3(float %arg0, i32 inreg %arg1, i32 inreg %arg2, i32 %arg3)
+    // CHECK: @f3(float %_1, i32 inreg %_2, i32 inreg %_3, i32 %_4)
     #[no_mangle]
     pub extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}
 
-    // CHECK: @f4(i32 inreg %arg0, float %arg1, i32 inreg %arg2, i32 %arg3)
+    // CHECK: @f4(i32 inreg %_1, float %_2, i32 inreg %_3, i32 %_4)
     #[no_mangle]
     pub extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}
 
-    // CHECK: @f5(i64 %arg0, i32 %arg1)
+    // CHECK: @f5(i64 %_1, i32 %_2)
     #[no_mangle]
     pub extern "fastcall" fn f5(_: i64, _: i32) {}
 
-    // CHECK: @f6(i1 inreg zeroext %arg0, i32 inreg %arg1, i32 %arg2)
+    // CHECK: @f6(i1 inreg zeroext %_1, i32 inreg %_2, i32 %_3)
     #[no_mangle]
     pub extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
 }
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index bd121ef2..7e1791c 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -18,48 +18,48 @@
   x
 }
 
-// CHECK: @readonly_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0)
+// CHECK: @readonly_borrow(i32* noalias readonly align 4 dereferenceable(4) %_1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn readonly_borrow(_: &i32) {
 }
 
-// CHECK: @static_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0)
+// CHECK: @static_borrow(i32* noalias readonly align 4 dereferenceable(4) %_1)
 // static borrow may be captured
 #[no_mangle]
 pub fn static_borrow(_: &'static i32) {
 }
 
-// CHECK: @named_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0)
+// CHECK: @named_borrow(i32* noalias readonly align 4 dereferenceable(4) %_1)
 // borrow with named lifetime may be captured
 #[no_mangle]
 pub fn named_borrow<'r>(_: &'r i32) {
 }
 
-// CHECK: @unsafe_borrow(i16* align 2 dereferenceable(2) %arg0)
+// CHECK: @unsafe_borrow(i16* align 2 dereferenceable(2) %_1)
 // unsafe interior means this isn't actually readonly and there may be aliases ...
 #[no_mangle]
 pub fn unsafe_borrow(_: &UnsafeInner) {
 }
 
-// CHECK: @mutable_unsafe_borrow(i16* align 2 dereferenceable(2) %arg0)
+// CHECK: @mutable_unsafe_borrow(i16* align 2 dereferenceable(2) %_1)
 // ... unless this is a mutable borrow, those never alias
 #[no_mangle]
 pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {
 }
 
-// CHECK: @mutable_borrow(i32* align 4 dereferenceable(4) %arg0)
+// CHECK: @mutable_borrow(i32* align 4 dereferenceable(4) %_1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn mutable_borrow(_: &mut i32) {
 }
 
-// CHECK: @indirect_struct(%S* noalias nocapture dereferenceable(32) %arg0)
+// CHECK: @indirect_struct(%S* noalias nocapture dereferenceable(32) %_1)
 #[no_mangle]
 pub fn indirect_struct(_: S) {
 }
 
-// CHECK: @borrowed_struct(%S* noalias readonly align 4 dereferenceable(32) %arg0)
+// CHECK: @borrowed_struct(%S* noalias readonly align 4 dereferenceable(32) %_1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn borrowed_struct(_: &S) {
@@ -80,36 +80,36 @@
 }
 
 // Hack to get the correct size for the length part in slices
-// CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
+// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
 #[no_mangle]
 pub fn helper(_: usize) {
 }
 
-// CHECK: @slice([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1)
+// CHECK: @slice([0 x i8]* noalias nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn slice(_: &[u8]) {
 }
 
-// CHECK: @mutable_slice([0 x i8]* nonnull align 1 %arg0.0, [[USIZE]] %arg0.1)
+// CHECK: @mutable_slice([0 x i8]* nonnull align 1 %_1.0, [[USIZE]] %_1.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn mutable_slice(_: &mut [u8]) {
 }
 
-// CHECK: @unsafe_slice([0 x i16]* nonnull align 2 %arg0.0, [[USIZE]] %arg0.1)
+// CHECK: @unsafe_slice([0 x i16]* nonnull align 2 %_1.0, [[USIZE]] %_1.1)
 // unsafe interior means this isn't actually readonly and there may be aliases ...
 #[no_mangle]
 pub fn unsafe_slice(_: &[UnsafeInner]) {
 }
 
-// CHECK: @str([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1)
+// CHECK: @str([0 x i8]* noalias nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn str(_: &[u8]) {
 }
 
-// CHECK: @trait_borrow({}* nonnull align 1 %arg0.0, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}) %arg0.1)
+// CHECK: @trait_borrow({}* nonnull align 1 %_1.0, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn trait_borrow(_: &Drop) {
diff --git a/src/test/codegen/personality_lifetimes.rs b/src/test/codegen/personality_lifetimes.rs
index 0d3d537..05888c0 100644
--- a/src/test/codegen/personality_lifetimes.rs
+++ b/src/test/codegen/personality_lifetimes.rs
@@ -20,12 +20,13 @@
     let _s = S;
     // Check that the personality slot alloca gets a lifetime start in each cleanup block, not just
     // in the first one.
+    // CHECK: [[SLOT:%[0-9]+]] = alloca { i8*, i32 }
     // CHECK-LABEL: cleanup:
-    // CHECK: bitcast{{.*}}personalityslot
-    // CHECK-NEXT: call void @llvm.lifetime.start
+    // CHECK: [[BITCAST:%[0-9]+]] = bitcast { i8*, i32 }* [[SLOT]] to i8*
+    // CHECK-NEXT: call void @llvm.lifetime.start.{{.*}}({{.*}}, i8* [[BITCAST]])
     // CHECK-LABEL: cleanup1:
-    // CHECK: bitcast{{.*}}personalityslot
-    // CHECK-NEXT: call void @llvm.lifetime.start
+    // CHECK: [[BITCAST1:%[0-9]+]] = bitcast { i8*, i32 }* [[SLOT]] to i8*
+    // CHECK-NEXT: call void @llvm.lifetime.start.{{.*}}({{.*}}, i8* [[BITCAST1]])
     might_unwind();
     let _t = S;
     might_unwind();
diff --git a/src/test/codegen/refs.rs b/src/test/codegen/refs.rs
index cbb9942..15f99fd 100644
--- a/src/test/codegen/refs.rs
+++ b/src/test/codegen/refs.rs
@@ -3,7 +3,7 @@
 #![crate_type = "lib"]
 
 // Hack to get the correct size for the length part in slices
-// CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
+// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
 #[no_mangle]
 pub fn helper(_: usize) {
 }
diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs
index c348a8f..87f29f6 100644
--- a/src/test/codegen/repeat-trusted-len.rs
+++ b/src/test/codegen/repeat-trusted-len.rs
@@ -6,7 +6,7 @@
 
 use std::iter;
 
-// CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
+// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
 #[no_mangle]
 pub fn helper(_: usize) {
 }
diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs
index c9f3837..e705d5c 100644
--- a/src/test/codegen/repr-transparent.rs
+++ b/src/test/codegen/repr-transparent.rs
@@ -14,21 +14,21 @@
 #[repr(transparent)]
 pub struct F32(f32);
 
-// CHECK: define float @test_F32(float %arg0)
+// CHECK: define float @test_F32(float %_1)
 #[no_mangle]
 pub extern fn test_F32(_: F32) -> F32 { loop {} }
 
 #[repr(transparent)]
 pub struct Ptr(*mut u8);
 
-// CHECK: define i8* @test_Ptr(i8* %arg0)
+// CHECK: define i8* @test_Ptr(i8* %_1)
 #[no_mangle]
 pub extern fn test_Ptr(_: Ptr) -> Ptr { loop {} }
 
 #[repr(transparent)]
 pub struct WithZst(u64, Zst1);
 
-// CHECK: define i64 @test_WithZst(i64 %arg0)
+// CHECK: define i64 @test_WithZst(i64 %_1)
 #[no_mangle]
 pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} }
 
@@ -36,14 +36,14 @@
 pub struct WithZeroSizedArray(*const f32, [i8; 0]);
 
 // Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
-// CHECK: define i32* @test_WithZeroSizedArray(i32* %arg0)
+// CHECK: define i32* @test_WithZeroSizedArray(i32* %_1)
 #[no_mangle]
 pub extern fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
 
 #[repr(transparent)]
 pub struct Generic<T>(T);
 
-// CHECK: define double @test_Generic(double %arg0)
+// CHECK: define double @test_Generic(double %_1)
 #[no_mangle]
 pub extern fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
 
@@ -53,14 +53,14 @@
 #[repr(u8)]
 pub enum Bool { True, False, FileNotFound }
 
-// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %arg0)
+// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1)
 #[no_mangle]
 pub extern fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
 
 #[repr(transparent)]
 pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
 
-// CHECK: define i16* @test_LifetimePhantom(i16* %arg0)
+// CHECK: define i16* @test_LifetimePhantom(i16* %_1)
 #[no_mangle]
 pub extern fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
 
@@ -70,28 +70,28 @@
 
 pub struct Px;
 
-// CHECK: define float @test_UnitPhantom(float %arg0)
+// CHECK: define float @test_UnitPhantom(float %_1)
 #[no_mangle]
 pub extern fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
 
 #[repr(transparent)]
 pub struct TwoZsts(Zst1, i8, Zst2);
 
-// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %arg0)
+// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1)
 #[no_mangle]
 pub extern fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
 
 #[repr(transparent)]
 pub struct Nested1(Zst2, Generic<f64>);
 
-// CHECK: define double @test_Nested1(double %arg0)
+// CHECK: define double @test_Nested1(double %_1)
 #[no_mangle]
 pub extern fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
 
 #[repr(transparent)]
 pub struct Nested2(Nested1, Zst1);
 
-// CHECK: define double @test_Nested2(double %arg0)
+// CHECK: define double @test_Nested2(double %_1)
 #[no_mangle]
 pub extern fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
 
@@ -101,7 +101,7 @@
 #[repr(transparent)]
 pub struct Vector(f32x4);
 
-// CHECK: define <4 x float> @test_Vector(<4 x float> %arg0)
+// CHECK: define <4 x float> @test_Vector(<4 x float> %_1)
 #[no_mangle]
 pub extern fn test_Vector(_: Vector) -> Vector { loop {} }
 
@@ -111,7 +111,7 @@
 #[repr(transparent)]
 pub struct StructWithProjection(<f32 as Mirror>::It);
 
-// CHECK: define float @test_Projection(float %arg0)
+// CHECK: define float @test_Projection(float %_1)
 #[no_mangle]
 pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
 
@@ -120,7 +120,7 @@
     Variant(F32)
 }
 
-// CHECK: define float @test_EnumF32(float %arg0)
+// CHECK: define float @test_EnumF32(float %_1)
 #[no_mangle]
 pub extern fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }
 
@@ -129,7 +129,7 @@
     Variant(Zst1, F32, Zst2)
 }
 
-// CHECK: define float @test_EnumF32WithZsts(float %arg0)
+// CHECK: define float @test_EnumF32WithZsts(float %_1)
 #[no_mangle]
 pub extern fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }
 
@@ -138,7 +138,7 @@
     field: F32,
 }
 
-// CHECK: define float @test_UnionF32(float %arg0)
+// CHECK: define float @test_UnionF32(float %_1)
 #[no_mangle]
 pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
 
@@ -149,7 +149,7 @@
     zst2: Zst2,
 }
 
-// CHECK: define float @test_UnionF32WithZsts(float %arg0)
+// CHECK: define float @test_UnionF32WithZsts(float %_1)
 #[no_mangle]
 pub extern fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} }
 
diff --git a/src/test/codegen/scalar-pair-bool.rs b/src/test/codegen/scalar-pair-bool.rs
index 78d1025..d91ee7f 100644
--- a/src/test/codegen/scalar-pair-bool.rs
+++ b/src/test/codegen/scalar-pair-bool.rs
@@ -20,24 +20,24 @@
     pair
 }
 
-// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %arg0.0, i1 zeroext %arg0.1)
+// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %_1.0, i1 zeroext %_1.1)
 #[no_mangle]
 pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) {
     // Make sure it can operate directly on the unpacked args
-    // CHECK: and i1 %arg0.0, %arg0.1
-    // CHECK: or i1 %arg0.0, %arg0.1
+    // CHECK: and i1 %_1.0, %_1.1
+    // CHECK: or i1 %_1.0, %_1.1
     (a && b, a || b)
 }
 
-// CHECK: define void @pair_branches(i1 zeroext %arg0.0, i1 zeroext %arg0.1)
+// CHECK: define void @pair_branches(i1 zeroext %_1.0, i1 zeroext %_1.1)
 #[no_mangle]
 pub fn pair_branches((a, b): (bool, bool)) {
     // Make sure it can branch directly on the unpacked bool args
-    // CHECK: br i1 %arg0.0
+    // CHECK: br i1 %_1.0
     if a {
         println!("Hello!");
     }
-    // CHECK: br i1 %arg0.1
+    // CHECK: br i1 %_1.1
     if b {
         println!("Goodbye!");
     }
diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs
index b7baffe..7339df1 100644
--- a/src/test/codegen/union-abi.rs
+++ b/src/test/codegen/union-abi.rs
@@ -16,38 +16,38 @@
 #[derive(Copy, Clone)]
 pub union UnionI64x4{ a:(), b: i64x4 }
 
-// CHECK: define void @test_UnionI64x4(<4 x i64>* {{.*}} %arg0)
+// CHECK: define void @test_UnionI64x4(<4 x i64>* {{.*}} %_1)
 #[no_mangle]
 pub fn test_UnionI64x4(_: UnionI64x4) { loop {} }
 
 pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 }
 
-// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %arg0)
+// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %_1)
 #[no_mangle]
 pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} }
 
 pub union UnionI64x4I64{ a: i64x4, b: i64 }
 
-// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %arg0)
+// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %_1)
 #[no_mangle]
 pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} }
 
 pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) }
 
-// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %arg0)
+// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %_1)
 #[no_mangle]
 pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} }
 
 
 pub union UnionF32{a:f32}
 
-// CHECK: define float @test_UnionF32(float %arg0)
+// CHECK: define float @test_UnionF32(float %_1)
 #[no_mangle]
 pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
 
 pub union UnionF32F32{a:f32, b:f32}
 
-// CHECK: define float @test_UnionF32F32(float %arg0)
+// CHECK: define float @test_UnionF32F32(float %_1)
 #[no_mangle]
 pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} }
 
@@ -58,13 +58,13 @@
 pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }
 
 pub union UnionU128{a:u128}
-// CHECK: define i128 @test_UnionU128(i128 %arg0)
+// CHECK: define i128 @test_UnionU128(i128 %_1)
 #[no_mangle]
 pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} }
 
 #[repr(C)]
 pub union CUnionU128{a:u128}
-// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %arg0)
+// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %_1)
 #[no_mangle]
 pub fn test_CUnionU128(_: CUnionU128) { loop {} }
 
diff --git a/src/test/codegen/var-names.rs b/src/test/codegen/var-names.rs
new file mode 100644
index 0000000..3140a7c
--- /dev/null
+++ b/src/test/codegen/var-names.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: define i32 @test(i32 %a, i32 %b)
+#[no_mangle]
+pub fn test(a: u32, b: u32) -> u32 {
+    let c = a + b;
+    // CHECK: %c = add i32 %a, %b
+    let d = c;
+    let e = d * a;
+    // CHECK-NEXT: %e = mul i32 %c, %a
+    e
+    // CHECK-NEXT: ret i32 %e
+}
diff --git a/src/test/ui/issues/issue-44415.rs b/src/test/compile-fail/issue-44415.rs
similarity index 100%
rename from src/test/ui/issues/issue-44415.rs
rename to src/test/compile-fail/issue-44415.rs
diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs
index c0ff90c..8709fb6 100644
--- a/src/test/debuginfo/boxed-struct.rs
+++ b/src/test/debuginfo/boxed-struct.rs
@@ -8,11 +8,11 @@
 
 // gdb-command:run
 
-// gdb-command:print *unique
+// gdb-command:print *boxed_with_padding
 // gdbg-check:$1 = {x = 99, y = 999, z = 9999, w = 99999}
 // gdbr-check:$1 = boxed_struct::StructWithSomePadding {x: 99, y: 999, z: 9999, w: 99999}
 
-// gdb-command:print *unique_dtor
+// gdb-command:print *boxed_with_dtor
 // gdbg-check:$2 = {x = 77, y = 777, z = 7777, w = 77777}
 // gdbr-check:$2 = boxed_struct::StructWithDestructor {x: 77, y: 777, z: 7777, w: 77777}
 
@@ -21,13 +21,13 @@
 
 // lldb-command:run
 
-// lldb-command:print *unique
+// lldb-command:print *boxed_with_padding
 // lldbg-check:[...]$0 = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
-// lldbr-check:(boxed_struct::StructWithSomePadding) *unique = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
+// lldbr-check:(boxed_struct::StructWithSomePadding) *boxed_with_padding = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
 
-// lldb-command:print *unique_dtor
+// lldb-command:print *boxed_with_dtor
 // lldbg-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
-// lldbr-check:(boxed_struct::StructWithDestructor) *unique_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
+// lldbr-check:(boxed_struct::StructWithDestructor) *boxed_with_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
@@ -54,9 +54,9 @@
 
 fn main() {
 
-    let unique: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
+    let boxed_with_padding: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
 
-    let unique_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
+    let boxed_with_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
     zzz(); // #break
 }
 
diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs
index fef6253..8c86d2c 100644
--- a/src/test/debuginfo/function-arg-initialization.rs
+++ b/src/test/debuginfo/function-arg-initialization.rs
@@ -242,12 +242,12 @@
 
 fn binding(a: i64, b: u64, c: f64) {
     let x = 0; // #break
-    println!("")
+    println!()
 }
 
 fn assignment(mut a: u64, b: u64, c: f64) {
     a = b; // #break
-    println!("")
+    println!()
 }
 
 fn function_call(x: u64, y: u64, z: f64) {
diff --git a/src/test/debuginfo/issue-22656.rs b/src/test/debuginfo/issue-22656.rs
index 86d3190..e4634d9 100644
--- a/src/test/debuginfo/issue-22656.rs
+++ b/src/test/debuginfo/issue-22656.rs
@@ -15,7 +15,7 @@
 // lldbg-check:[...]$0 = vec![1, 2, 3]
 // lldbr-check:(alloc::vec::Vec<i32>) v = vec![1, 2, 3]
 // lldb-command:print zs
-// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct, y: 123, z: ZeroSizedStruct, w: 456 }
+// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct[...], y: 123, z: ZeroSizedStruct[...], w: 456 }
 // lldbr-check:(issue_22656::StructWithZeroSizedField) zs = StructWithZeroSizedField { x: ZeroSizedStruct { }, y: 123, z: ZeroSizedStruct { }, w: 456 }
 // lldbr-command:continue
 
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index 4515e36..9cc2d3b 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -11,7 +11,6 @@
 
 
 #![allow(warnings)]
-#![feature(intrinsics)]
 #![feature(linkage)]
 #![feature(rustc_attrs)]
 #![crate_type = "rlib"]
@@ -99,17 +98,6 @@
 pub extern "C" fn make_extern() {}
 
 
-// Extern C Extern Rust-Intrinsic ----------------------------------------------
-
-#[cfg(cfail1)]
-pub extern "C" fn make_intrinsic() {}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")]
-#[rustc_clean(cfg = "cfail3")]
-pub extern "rust-intrinsic" fn make_intrinsic() {}
-
-
 // Type Parameter --------------------------------------------------------------
 
 #[cfg(cfail1)]
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
index 81ff995..3006cdc 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -18,7 +18,6 @@
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 #![feature(associated_type_defaults)]
-#![feature(intrinsics)]
 
 
 // Change trait visibility
@@ -318,7 +317,7 @@
 
 
 
-// Change extern "C" to extern "rust-intrinsic"
+// Change extern "C" to extern "stdcall"
 #[cfg(cfail1)]
 trait TraitChangeExternCToRustIntrinsic {
     extern "C" fn method();
@@ -330,7 +329,7 @@
 trait TraitChangeExternCToRustIntrinsic {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
-    extern "rust-intrinsic" fn method();
+    extern "stdcall" fn method();
 }
 
 
diff --git a/src/test/mir-opt/match-arm-scopes.rs b/src/test/mir-opt/match-arm-scopes.rs
index 18e0642..c898d3a 100644
--- a/src/test/mir-opt/match-arm-scopes.rs
+++ b/src/test/mir-opt/match-arm-scopes.rs
@@ -8,8 +8,6 @@
 //   all of the bindings for that scope.
 // * No drop flags are used.
 
-#![feature(nll, bind_by_move_pattern_guards)]
-
 fn complicated_match(cond: bool, items: (bool, bool, String)) -> i32 {
     match items {
         (false, a, s) | (a, false, s) if if cond { return 3 } else { a } => 1,
diff --git a/src/test/pretty/macro.rs b/src/test/pretty/macro.rs
index 39677d1..1e1e1db 100644
--- a/src/test/pretty/macro.rs
+++ b/src/test/pretty/macro.rs
@@ -2,6 +2,6 @@
 
 #![feature(decl_macro)]
 
-macro mac { ($ arg : expr) => { $ arg + $ arg } }
+pub(crate) macro mac { ($ arg : expr) => { $ arg + $ arg } }
 
 fn main() { }
diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk
index 3b4df73..9a113b7 100644
--- a/src/test/run-make-fulldeps/tools.mk
+++ b/src/test/run-make-fulldeps/tools.mk
@@ -12,7 +12,7 @@
 RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR)
 ifdef RUSTC_LINKER
 RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER)
-RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options
+RUSTDOC := $(RUSTDOC) -Clinker=$(RUSTC_LINKER)
 endif
 #CC := $(CC) -L $(TMPDIR)
 HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py
diff --git a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
index 42445b9..93c47d3 100644
--- a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
+++ b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
@@ -1,5 +1,3 @@
-// no-prefer-dynamic
-
 #![allow(dead_code)]
 
 // check dtor calling order when casting enums.
diff --git a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs
index 925ffe7..fb2b4d4 100644
--- a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs
+++ b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs
@@ -1,5 +1,3 @@
-// no-prefer-dynamic
-
 // This would previously leak the Box<Trait> because we wouldn't
 // schedule cleanups when auto borrowing trait objects.
 // This program should be valgrind clean.
diff --git a/src/test/run-pass-valgrind/cleanup-stdin.rs b/src/test/run-pass-valgrind/cleanup-stdin.rs
index 3505074..cf8f81c 100644
--- a/src/test/run-pass-valgrind/cleanup-stdin.rs
+++ b/src/test/run-pass-valgrind/cleanup-stdin.rs
@@ -1,5 +1,3 @@
-// no-prefer-dynamic
-
 fn main() {
     let _ = std::io::stdin();
     let _ = std::io::stdout();
diff --git a/src/test/run-pass-valgrind/down-with-thread-dtors.rs b/src/test/run-pass-valgrind/down-with-thread-dtors.rs
index c3567a9..8531b8d 100644
--- a/src/test/run-pass-valgrind/down-with-thread-dtors.rs
+++ b/src/test/run-pass-valgrind/down-with-thread-dtors.rs
@@ -1,4 +1,3 @@
-// no-prefer-dynamic
 // ignore-emscripten
 
 thread_local!(static FOO: Foo = Foo);
diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs
index 7533a7b..5b8433f 100644
--- a/src/test/run-pass-valgrind/dst-dtor-1.rs
+++ b/src/test/run-pass-valgrind/dst-dtor-1.rs
@@ -1,5 +1,3 @@
-// no-prefer-dynamic
-
 static mut DROP_RAN: bool = false;
 
 struct Foo;
diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs
index ebf0c17..991fe00 100644
--- a/src/test/run-pass-valgrind/dst-dtor-2.rs
+++ b/src/test/run-pass-valgrind/dst-dtor-2.rs
@@ -1,5 +1,3 @@
-// no-prefer-dynamic
-
 static mut DROP_RAN: isize = 0;
 
 struct Foo;
diff --git a/src/test/run-pass-valgrind/dst-dtor-3.rs b/src/test/run-pass-valgrind/dst-dtor-3.rs
index e15908d..f0c2dda 100644
--- a/src/test/run-pass-valgrind/dst-dtor-3.rs
+++ b/src/test/run-pass-valgrind/dst-dtor-3.rs
@@ -1,5 +1,3 @@
-// no-prefer-dynamic
-
 #![feature(unsized_tuple_coercion)]
 
 static mut DROP_RAN: bool = false;
diff --git a/src/test/run-pass-valgrind/dst-dtor-4.rs b/src/test/run-pass-valgrind/dst-dtor-4.rs
index 52bf0c3..ad6d46f 100644
--- a/src/test/run-pass-valgrind/dst-dtor-4.rs
+++ b/src/test/run-pass-valgrind/dst-dtor-4.rs
@@ -1,5 +1,3 @@
-// no-prefer-dynamic
-
 #![feature(unsized_tuple_coercion)]
 
 static mut DROP_RAN: isize = 0;
diff --git a/src/test/run-pass-valgrind/exit-flushes.rs b/src/test/run-pass-valgrind/exit-flushes.rs
index cd5edb8..a68c6f3 100644
--- a/src/test/run-pass-valgrind/exit-flushes.rs
+++ b/src/test/run-pass-valgrind/exit-flushes.rs
@@ -1,4 +1,3 @@
-// no-prefer-dynamic
 // ignore-cloudabi
 // ignore-emscripten
 // ignore-sgx no processes
diff --git a/src/test/run-pass-valgrind/osx-frameworks.rs b/src/test/run-pass-valgrind/osx-frameworks.rs
index 4ea804a..ea14036 100644
--- a/src/test/run-pass-valgrind/osx-frameworks.rs
+++ b/src/test/run-pass-valgrind/osx-frameworks.rs
@@ -1,4 +1,3 @@
-// no-prefer-dynamic
 // pretty-expanded FIXME #23616
 
 #![feature(rustc_private)]
diff --git a/src/test/rustdoc-js-std/vec-new.js b/src/test/rustdoc-js-std/vec-new.js
index e4daa50..e1a3256 100644
--- a/src/test/rustdoc-js-std/vec-new.js
+++ b/src/test/rustdoc-js-std/vec-new.js
@@ -4,5 +4,6 @@
     'others': [
         { 'path': 'std::vec::Vec', 'name': 'new' },
         { 'path': 'std::vec::Vec', 'name': 'ne' },
+        { 'path': 'std::rc::Rc', 'name': 'ne' },
     ],
 };
diff --git a/src/test/rustdoc-js/exact-match.js b/src/test/rustdoc-js/exact-match.js
new file mode 100644
index 0000000..b0a411b
--- /dev/null
+++ b/src/test/rustdoc-js/exact-match.js
@@ -0,0 +1,9 @@
+const QUERY = 'si::pc';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'exact_match::Si', 'name': 'pc' },
+        { 'path': 'exact_match::Psi', 'name': 'pc' },
+        { 'path': 'exact_match::Si', 'name': 'pa' },
+    ],
+};
diff --git a/src/test/rustdoc-js/exact-match.rs b/src/test/rustdoc-js/exact-match.rs
new file mode 100644
index 0000000..2eacc0a
--- /dev/null
+++ b/src/test/rustdoc-js/exact-match.rs
@@ -0,0 +1,68 @@
+macro_rules! imp {
+    ($name:ident) => {
+        pub struct $name {
+            pub op: usize,
+        }
+        impl $name {
+            pub fn op() {}
+            pub fn cmp() {}
+            pub fn map() {}
+            pub fn pop() {}
+            pub fn ptr() {}
+            pub fn rpo() {}
+            pub fn drop() {}
+            pub fn copy() {}
+            pub fn zip() {}
+            pub fn sup() {}
+            pub fn pa() {}
+            pub fn pb() {}
+            pub fn pc() {}
+            pub fn pd() {}
+            pub fn pe() {}
+            pub fn pf() {}
+            pub fn pg() {}
+            pub fn ph() {}
+            pub fn pi() {}
+            pub fn pj() {}
+            pub fn pk() {}
+            pub fn pl() {}
+            pub fn pm() {}
+            pub fn pn() {}
+            pub fn po() {}
+        }
+    };
+    ($name:ident, $($names:ident),*) => {
+        imp!($name);
+        imp!($($names),*);
+    };
+}
+macro_rules! en {
+    ($name:ident) => {
+        pub enum $name {
+            Ptr,
+            Rp,
+            Rpo,
+            Pt,
+            Drop,
+            Dr,
+            Dro,
+            Sup,
+            Op,
+            Cmp,
+            Map,
+            Mp,
+        }
+    };
+    ($name:ident, $($names:ident),*) => {
+        en!($name);
+        en!($($names),*);
+    };
+}
+
+imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd);
+imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp);
+imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp);
+
+en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar);
+
+pub struct P;
diff --git a/src/test/rustdoc-js/module-substring.js b/src/test/rustdoc-js/module-substring.js
new file mode 100644
index 0000000..a446c39
--- /dev/null
+++ b/src/test/rustdoc-js/module-substring.js
@@ -0,0 +1,9 @@
+const QUERY = 'ig::pc';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'module_substring::Sig', 'name': 'pc' },
+        { 'path': 'module_substring::Si', 'name': 'pc' },
+        { 'path': 'module_substring::Si', 'name': 'pa' },
+    ],
+};
diff --git a/src/test/rustdoc-js/module-substring.rs b/src/test/rustdoc-js/module-substring.rs
new file mode 100644
index 0000000..2eacc0a
--- /dev/null
+++ b/src/test/rustdoc-js/module-substring.rs
@@ -0,0 +1,68 @@
+macro_rules! imp {
+    ($name:ident) => {
+        pub struct $name {
+            pub op: usize,
+        }
+        impl $name {
+            pub fn op() {}
+            pub fn cmp() {}
+            pub fn map() {}
+            pub fn pop() {}
+            pub fn ptr() {}
+            pub fn rpo() {}
+            pub fn drop() {}
+            pub fn copy() {}
+            pub fn zip() {}
+            pub fn sup() {}
+            pub fn pa() {}
+            pub fn pb() {}
+            pub fn pc() {}
+            pub fn pd() {}
+            pub fn pe() {}
+            pub fn pf() {}
+            pub fn pg() {}
+            pub fn ph() {}
+            pub fn pi() {}
+            pub fn pj() {}
+            pub fn pk() {}
+            pub fn pl() {}
+            pub fn pm() {}
+            pub fn pn() {}
+            pub fn po() {}
+        }
+    };
+    ($name:ident, $($names:ident),*) => {
+        imp!($name);
+        imp!($($names),*);
+    };
+}
+macro_rules! en {
+    ($name:ident) => {
+        pub enum $name {
+            Ptr,
+            Rp,
+            Rpo,
+            Pt,
+            Drop,
+            Dr,
+            Dro,
+            Sup,
+            Op,
+            Cmp,
+            Map,
+            Mp,
+        }
+    };
+    ($name:ident, $($names:ident),*) => {
+        en!($name);
+        en!($($names),*);
+    };
+}
+
+imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd);
+imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp);
+imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp);
+
+en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar);
+
+pub struct P;
diff --git a/src/test/rustdoc-js/search-short-types.js b/src/test/rustdoc-js/search-short-types.js
index 0ebf486..d14672a 100644
--- a/src/test/rustdoc-js/search-short-types.js
+++ b/src/test/rustdoc-js/search-short-types.js
@@ -3,6 +3,8 @@
 const EXPECTED = {
     'others': [
         { 'path': 'search_short_types', 'name': 'P' },
+        { 'path': 'search_short_types::VeryLongTypeName', 'name': 'p' },
         { 'path': 'search_short_types', 'name': 'Ap' },
+        { 'path': 'search_short_types::VeryLongTypeName', 'name': 'ap' },
     ],
 };
diff --git a/src/test/rustdoc-js/search-short-types.rs b/src/test/rustdoc-js/search-short-types.rs
index 2eacc0a..a4083f9 100644
--- a/src/test/rustdoc-js/search-short-types.rs
+++ b/src/test/rustdoc-js/search-short-types.rs
@@ -66,3 +66,9 @@
 en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar);
 
 pub struct P;
+
+pub struct VeryLongTypeName;
+impl VeryLongTypeName {
+    pub fn p() {}
+    pub fn ap() {}
+}
diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs
index 2b02d47..97a0f4a 100644
--- a/src/test/rustdoc-ui/invalid-syntax.rs
+++ b/src/test/rustdoc-ui/invalid-syntax.rs
@@ -64,3 +64,21 @@
 /// \_
 #[doc = "```"]
 pub fn crazy_attrs() {}
+
+/// ```rust
+/// ```
+pub fn empty_rust() {}
+
+/// ```
+///
+///
+/// ```
+pub fn empty_rust_with_whitespace() {}
+
+/// ```
+/// let x = 1;
+/// ```
+///
+///     \____/
+///
+pub fn indent_after_fenced() {}
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
index 3bebbec..6f50eda 100644
--- a/src/test/rustdoc-ui/invalid-syntax.stderr
+++ b/src/test/rustdoc-ui/invalid-syntax.stderr
@@ -179,6 +179,46 @@
    |
    = help: mark blocks that do not contain Rust code as text: ```text
 
+warning: Rust code block is empty
+  --> $DIR/invalid-syntax.rs:68:5
+   |
+LL |   /// ```rust
+   |  _____^
+LL | | /// ```
+   | |_______^
+
+warning: Rust code block is empty
+  --> $DIR/invalid-syntax.rs:72:5
+   |
+LL |   /// ```
+   |  _____^
+LL | | ///
+LL | | ///
+LL | | /// ```
+   | |_______^
+help: mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text
+   |     ^^^^^^^
+
+error: unknown start of token: \
+ --> <doctest>:1:1
+  |
+1 | \____/
+  | ^
+
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:82:9
+   |
+LL | ///     \____/
+   |         ^^^^^^
+
+error: unknown start of token: \
+ --> <rustdoc-highlighting>:1:1
+  |
+1 | \____/
+  | ^
+
 error: unknown start of token: \
  --> <rustdoc-highlighting>:1:1
   |
diff --git a/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs b/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs
new file mode 100644
index 0000000..5c4a01e
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs
@@ -0,0 +1,20 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+#![crate_name="some_macros"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    item // This doesn't erase the spans.
+}
+
+#[proc_macro_attribute]
+pub fn second(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    // Make a new `TokenStream` to erase the spans:
+    let mut out: TokenStream = TokenStream::new();
+    out.extend(item);
+    out
+}
diff --git a/src/test/rustdoc/inline_cross/proc_macro.rs b/src/test/rustdoc/inline_cross/proc_macro.rs
index 6880e30..3dc8de3 100644
--- a/src/test/rustdoc/inline_cross/proc_macro.rs
+++ b/src/test/rustdoc/inline_cross/proc_macro.rs
@@ -10,8 +10,19 @@
 // @has proc_macro/macro.some_proc_macro.html
 // @has proc_macro/attr.some_proc_attr.html
 // @has proc_macro/derive.SomeDerive.html
-pub use some_macros::{some_proc_macro, some_proc_attr, SomeDerive};
+
+// @has proc_macro/macro.some_proc_macro.html
+// @has - 'a proc-macro that swallows its input and does nothing.'
+pub use some_macros::some_proc_macro;
 
 // @has proc_macro/macro.reexported_macro.html
 // @has - 'Doc comment from the original crate'
 pub use some_macros::reexported_macro;
+
+// @has proc_macro/attr.some_proc_attr.html
+// @has - 'a proc-macro attribute that passes its item through verbatim.'
+pub use some_macros::some_proc_attr;
+
+// @has proc_macro/derive.SomeDerive.html
+// @has - 'a derive attribute that adds nothing to its input.'
+pub use some_macros::SomeDerive;
diff --git a/src/test/rustdoc/through-proc-macro.rs b/src/test/rustdoc/through-proc-macro.rs
new file mode 100644
index 0000000..348c9ee
--- /dev/null
+++ b/src/test/rustdoc/through-proc-macro.rs
@@ -0,0 +1,12 @@
+// aux-build:through-proc-macro-aux.rs
+// build-aux-docs
+#![warn(intra_doc_link_resolution_failure)]
+extern crate some_macros;
+
+#[some_macros::second]
+pub enum Boom {
+    /// [Oooops]
+    Bam,
+}
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs
index 027025b..2b57e92 100644
--- a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs
+++ b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs
@@ -15,12 +15,12 @@
 extern crate rustc_driver;
 
 use syntax::parse::token::{self, Token};
-use syntax::tokenstream::TokenTree;
+use syntax::tokenstream::{TokenTree, TokenStream};
 use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
 use syntax_pos::Span;
 use rustc_driver::plugin::Registry;
 
-fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
+fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: TokenStream)
         -> Box<dyn MacResult + 'static> {
 
     static NUMERALS: &'static [(&'static str, usize)] = &[
@@ -36,7 +36,7 @@
         return DummyResult::any(sp);
     }
 
-    let text = match args[0] {
+    let text = match args.into_trees().next().unwrap() {
         TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(),
         _ => {
             cx.span_err(sp, "argument should be a single identifier");
diff --git a/src/test/ui-fulldeps/compiler-calls.rs b/src/test/ui-fulldeps/compiler-calls.rs
index ea24f58..bd9113c 100644
--- a/src/test/ui-fulldeps/compiler-calls.rs
+++ b/src/test/ui-fulldeps/compiler-calls.rs
@@ -24,7 +24,7 @@
 fn main() {
     let mut count = 1;
     let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
-    rustc_driver::report_ices_to_stderr_if_any(|| {
+    rustc_driver::catch_fatal_errors(|| {
         rustc_driver::run_compiler(&args, &mut TestCalls { count: &mut count }, None, None).ok();
     }).ok();
     assert_eq!(count, 2);
diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.rs b/src/test/ui-fulldeps/hash-stable-is-unstable.rs
index 9f67f64..d79ef62 100644
--- a/src/test/ui-fulldeps/hash-stable-is-unstable.rs
+++ b/src/test/ui-fulldeps/hash-stable-is-unstable.rs
@@ -13,3 +13,5 @@
 #[derive(HashStable)]
 //~^ use of unstable library feature 'rustc_private'
 struct Test;
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr
index 02056d3..e2dc0c3 100644
--- a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr
+++ b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `hash_stable_is_unstable`
-   |
-   = note: consider adding a `main` function to `$DIR/hash-stable-is-unstable.rs`
-
 error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/hash-stable-is-unstable.rs:3:1
    |
@@ -47,7 +43,6 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/27812
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0601, E0658.
-For more information about an error, try `rustc --explain E0601`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
index 09f5852..596f515 100644
--- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -32,13 +32,15 @@
 use syntax::ptr::P;
 
 
-fn parse_expr(ps: &ParseSess, src: &str) -> P<Expr> {
+fn parse_expr(ps: &ParseSess, src: &str) -> Option<P<Expr>> {
     let src_as_string = src.to_string();
 
-    let mut p = parse::new_parser_from_source_str(ps,
-                                                  FileName::Custom(src_as_string.clone()),
-                                                  src_as_string);
-    p.parse_expr().unwrap()
+    let mut p = parse::new_parser_from_source_str(
+        ps,
+        FileName::Custom(src_as_string.clone()),
+        src_as_string,
+    );
+    p.parse_expr().map_err(|mut e| e.cancel()).ok()
 }
 
 
@@ -150,12 +152,12 @@
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e)));
             },
             19 => {
-                let ps = vec![P(Pat {
+                let pat = P(Pat {
                     id: DUMMY_NODE_ID,
                     node: PatKind::Wild,
                     span: DUMMY_SP,
-                })];
-                iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(ps.clone(), e)))
+                });
+                iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e)))
             },
             _ => panic!("bad counter value in iter_exprs"),
         }
@@ -209,22 +211,23 @@
         let printed = pprust::expr_to_string(&e);
         println!("printed: {}", printed);
 
-        let mut parsed = parse_expr(&ps, &printed);
-
-        // We want to know if `parsed` is structurally identical to `e`, ignoring trivial
-        // differences like placement of `Paren`s or the exact ranges of node spans.
-        // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s
-        // everywhere we can, then pretty-print. This should give an unambiguous representation of
-        // each `Expr`, and it bypasses nearly all of the parenthesization logic, so we aren't
-        // relying on the correctness of the very thing we're testing.
-        RemoveParens.visit_expr(&mut e);
-        AddParens.visit_expr(&mut e);
-        let text1 = pprust::expr_to_string(&e);
-        RemoveParens.visit_expr(&mut parsed);
-        AddParens.visit_expr(&mut parsed);
-        let text2 = pprust::expr_to_string(&parsed);
-        assert!(text1 == text2,
-                "exprs are not equal:\n  e =      {:?}\n  parsed = {:?}",
-                text1, text2);
+        // Ignore expressions with chained comparisons that fail to parse
+        if let Some(mut parsed) = parse_expr(&ps, &printed) {
+            // We want to know if `parsed` is structurally identical to `e`, ignoring trivial
+            // differences like placement of `Paren`s or the exact ranges of node spans.
+            // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s
+            // everywhere we can, then pretty-print. This should give an unambiguous representation
+            // of each `Expr`, and it bypasses nearly all of the parenthesization logic, so we
+            // aren't relying on the correctness of the very thing we're testing.
+            RemoveParens.visit_expr(&mut e);
+            AddParens.visit_expr(&mut e);
+            let text1 = pprust::expr_to_string(&e);
+            RemoveParens.visit_expr(&mut parsed);
+            AddParens.visit_expr(&mut parsed);
+            let text2 = pprust::expr_to_string(&parsed);
+            assert!(text1 == text2,
+                    "exprs are not equal:\n  e =      {:?}\n  parsed = {:?}",
+                    text1, text2);
+        }
     });
 }
diff --git a/src/test/ui/allocator/hygiene.rs b/src/test/ui/allocator/hygiene.rs
new file mode 100644
index 0000000..9bd8406
--- /dev/null
+++ b/src/test/ui/allocator/hygiene.rs
@@ -0,0 +1,31 @@
+// run-pass
+// no-prefer-dynamic
+// aux-build:custom.rs
+// aux-build:helper.rs
+
+#![allow(nonstandard_style)]
+
+extern crate custom;
+extern crate helper;
+
+use custom::A;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+#[allow(dead_code)]
+struct u8;
+#[allow(dead_code)]
+struct usize;
+#[allow(dead_code)]
+static arg0: () = ();
+
+#[global_allocator]
+pub static GLOBAL: A = A(AtomicUsize::new(0));
+
+fn main() {
+    let n = GLOBAL.0.load(Ordering::SeqCst);
+    let s = Box::new(0);
+    helper::work_with(&s);
+    assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
+    drop(s);
+    assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+}
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
index 0ca3ca8..c65a44b 100644
--- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
@@ -5,12 +5,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _`
-   |
-note: required by `f1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1
-   |
+...
 LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ------------------------------------ required by `f1`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5
@@ -19,12 +16,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `fn(&(), &()) -> _`
-   |
-note: required by `f1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1
-   |
+...
 LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ------------------------------------ required by `f1`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -33,12 +27,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _`
-   |
-note: required by `f2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1
-   |
+...
 LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ----------------------------------------------- required by `f2`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -47,12 +38,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `fn(&'a (), &()) -> _`
-   |
-note: required by `f2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1
-   |
+...
 LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ----------------------------------------------- required by `f2`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -61,12 +49,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `for<'r> fn(&(), &'r ()) -> _`
-   |
-note: required by `f3`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1
-   |
+...
 LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ------------------------------------------- required by `f3`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -75,12 +60,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `fn(&(), &()) -> _`
-   |
-note: required by `f3`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1
-   |
+...
 LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ------------------------------------------- required by `f3`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
@@ -89,12 +71,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _`
-   |
-note: required by `f4`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1
-   |
+...
 LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ----------------------------------------------- required by `f4`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
@@ -103,12 +82,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `fn(&(), &'r ()) -> _`
-   |
-note: required by `f4`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1
-   |
+...
 LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ----------------------------------------------- required by `f4`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
@@ -117,12 +93,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `for<'r> fn(&'r (), &'r ()) -> _`
-   |
-note: required by `f5`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1
-   |
+...
 LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------------------- required by `f5`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
@@ -131,12 +104,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `fn(&'r (), &'r ()) -> _`
-   |
-note: required by `f5`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1
-   |
+...
 LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------------------- required by `f5`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -145,12 +115,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `for<'r> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>) -> _`
-   |
-note: required by `g1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1
-   |
+...
 LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ------------------------------------------------- required by `g1`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -159,12 +126,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
-   |
-note: required by `g1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1
-   |
+...
 LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ------------------------------------------------- required by `g1`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
@@ -173,12 +137,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _`
-   |
-note: required by `g2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1
-   |
+...
 LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ---------------------------------------- required by `g2`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
@@ -187,12 +148,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `fn(&(), for<'r> fn(&'r ())) -> _`
-   |
-note: required by `g2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1
-   |
+...
 LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ---------------------------------------- required by `g2`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
@@ -201,12 +159,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `for<'s> fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
-   |
-note: required by `g3`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1
-   |
+...
 LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ------------------------------------------------------------ required by `g3`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
@@ -215,12 +170,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
-   |
-note: required by `g3`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1
-   |
+...
 LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ------------------------------------------------------------ required by `g3`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
@@ -229,12 +181,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _`
-   |
-note: required by `g4`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1
-   |
+...
 LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | --------------------------------------------------- required by `g4`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
@@ -243,12 +192,9 @@
    |     ^^ -------------- found signature of `fn((), ()) -> _`
    |     |
    |     expected signature of `fn(&(), for<'r> fn(&'r ())) -> _`
-   |
-note: required by `g4`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1
-   |
+...
 LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | --------------------------------------------------- required by `g4`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
@@ -257,12 +203,9 @@
    |     ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
    |     |
    |     expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<(dyn for<'t0> std::ops::Fn(&'t0 ()) + 'static)>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
-   |
-note: required by `h1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
-   |
+...
 LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------------------------------------- required by `h1`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
@@ -271,12 +214,9 @@
    |     ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
    |     |
    |     expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &(), for<'r, 's> fn(&'r (), &'s ())) -> _`
-   |
-note: required by `h1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
-   |
+...
 LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------------------------------------- required by `h1`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
@@ -285,12 +225,9 @@
    |     ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
    |     |
    |     expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
-   |
-note: required by `h2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1
-   |
+...
 LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | --------------------------------------------------------------------------------- required by `h2`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
@@ -299,12 +236,9 @@
    |     ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
    |     |
    |     expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _`
-   |
-note: required by `h2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1
-   |
+...
 LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | --------------------------------------------------------------------------------- required by `h2`
 
 error: aborting due to 22 previous errors
 
diff --git a/src/test/ui/asm/asm-out-read-uninit.rs b/src/test/ui/asm/asm-out-read-uninit.rs
index 003f1fc..78458ff 100644
--- a/src/test/ui/asm/asm-out-read-uninit.rs
+++ b/src/test/ui/asm/asm-out-read-uninit.rs
@@ -20,7 +20,7 @@
     let x: isize;
     unsafe {
         asm!("mov $1, $0" : "=r"(x) : "r"(x));
-        //~^ ERROR use of possibly uninitialized variable: `x`
+        //~^ ERROR use of possibly-uninitialized variable: `x`
     }
     foo(x);
 }
diff --git a/src/test/ui/asm/asm-out-read-uninit.stderr b/src/test/ui/asm/asm-out-read-uninit.stderr
index 6d0445d..71aeda2 100644
--- a/src/test/ui/asm/asm-out-read-uninit.stderr
+++ b/src/test/ui/asm/asm-out-read-uninit.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/asm-out-read-uninit.rs:22:43
    |
 LL |         asm!("mov $1, $0" : "=r"(x) : "r"(x));
-   |                                           ^ use of possibly uninitialized `x`
+   |                                           ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-const/associated-const-array-len.stderr b/src/test/ui/associated-const/associated-const-array-len.stderr
index ff56d11..2fdfa3da 100644
--- a/src/test/ui/associated-const/associated-const-array-len.stderr
+++ b/src/test/ui/associated-const/associated-const-array-len.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/associated-const-array-len.rs:5:16
    |
+LL |     const ID: usize;
+   |     ---------------- required by `Foo::ID`
+...
 LL | const X: [i32; <i32 as Foo>::ID] = [0, 1, 2];
    |                ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
-   |
-note: required by `Foo::ID`
-  --> $DIR/associated-const-array-len.rs:2:5
-   |
-LL |     const ID: usize;
-   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-const/associated-const-in-trait.stderr b/src/test/ui/associated-const/associated-const-in-trait.stderr
index dff268a..a5d7fc5 100644
--- a/src/test/ui/associated-const/associated-const-in-trait.stderr
+++ b/src/test/ui/associated-const/associated-const-in-trait.stderr
@@ -1,10 +1,11 @@
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/associated-const-in-trait.rs:9:6
    |
+LL |     const N: usize;
+   |           - the trait cannot contain associated consts like `N`
+...
 LL | impl dyn Trait {
    |      ^^^^^^^^^ the trait `Trait` cannot be made into an object
-   |
-   = note: the trait cannot contain associated consts like `N`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr
index 573b8ed..30b6b4f 100644
--- a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `A: Foo` is not satisfied
   --> $DIR/associated-const-type-parameter-arrays-2.rs:16:22
    |
+LL |     const Y: usize;
+   |     --------------- required by `Foo::Y`
+...
 LL |     let _array = [4; <A as Foo>::Y];
    |                      ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
    |
    = help: consider adding a `where A: Foo` bound
-note: required by `Foo::Y`
-  --> $DIR/associated-const-type-parameter-arrays-2.rs:2:5
-   |
-LL |     const Y: usize;
-   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr
index bf1ee38..30fa989 100644
--- a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr
+++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `A: Foo` is not satisfied
   --> $DIR/associated-const-type-parameter-arrays.rs:16:23
    |
+LL |     const Y: usize;
+   |     --------------- required by `Foo::Y`
+...
 LL |     let _array: [u32; <A as Foo>::Y];
    |                       ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
    |
    = help: consider adding a `where A: Foo` bound
-note: required by `Foo::Y`
-  --> $DIR/associated-const-type-parameter-arrays.rs:2:5
-   |
-LL |     const Y: usize;
-   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
index aebf29c..06e8230 100644
--- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
+++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
@@ -24,6 +24,9 @@
 error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be sent between threads safely
   --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
    |
+LL |   trait Case1 {
+   |   ----------- required by `Case1`
+...
 LL | / fn assume_case1<T: Case1>() {
 LL | |
 LL | |
@@ -35,15 +38,13 @@
    |
    = help: the trait `std::marker::Send` is not implemented for `<<T as Case1>::C as std::iter::Iterator>::Item`
    = help: consider adding a `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Send` bound
-note: required by `Case1`
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:1
-   |
-LL | trait Case1 {
-   | ^^^^^^^^^^^
 
 error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be shared between threads safely
   --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
    |
+LL |   trait Case1 {
+   |   ----------- required by `Case1`
+...
 LL | / fn assume_case1<T: Case1>() {
 LL | |
 LL | |
@@ -55,15 +56,13 @@
    |
    = help: the trait `std::marker::Sync` is not implemented for `<<T as Case1>::C as std::iter::Iterator>::Item`
    = help: consider adding a `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Sync` bound
-note: required by `Case1`
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:1
-   |
-LL | trait Case1 {
-   | ^^^^^^^^^^^
 
 error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `std::fmt::Debug`
   --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
    |
+LL |   trait Case1 {
+   |   ----------- required by `Case1`
+...
 LL | / fn assume_case1<T: Case1>() {
 LL | |
 LL | |
@@ -74,11 +73,6 @@
    | |_^ `<_ as Lam<&'a u8>>::App` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
    |
    = help: the trait `for<'a> std::fmt::Debug` is not implemented for `<_ as Lam<&'a u8>>::App`
-note: required by `Case1`
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:1
-   |
-LL | trait Case1 {
-   | ^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs
index 9db5233..ceca54b 100644
--- a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs
+++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 #![feature(associated_type_bounds)]
 
diff --git a/src/test/ui/associated-type-bounds/fn-apit.rs b/src/test/ui/associated-type-bounds/fn-apit.rs
index 7e208b4..3c9f511 100644
--- a/src/test/ui/associated-type-bounds/fn-apit.rs
+++ b/src/test/ui/associated-type-bounds/fn-apit.rs
@@ -1,6 +1,7 @@
 // run-pass
 // aux-build:fn-aux.rs
 
+#![allow(unused)]
 #![feature(associated_type_bounds)]
 
 extern crate fn_aux;
diff --git a/src/test/ui/associated-type-bounds/fn-dyn-apit.rs b/src/test/ui/associated-type-bounds/fn-dyn-apit.rs
index 9ff4a50..c4e8092 100644
--- a/src/test/ui/associated-type-bounds/fn-dyn-apit.rs
+++ b/src/test/ui/associated-type-bounds/fn-dyn-apit.rs
@@ -1,6 +1,7 @@
 // run-pass
 // aux-build:fn-dyn-aux.rs
 
+#![allow(unused)]
 #![feature(associated_type_bounds)]
 
 extern crate fn_dyn_aux;
diff --git a/src/test/ui/associated-type-bounds/fn-inline.rs b/src/test/ui/associated-type-bounds/fn-inline.rs
index 7b18876..8fa7212 100644
--- a/src/test/ui/associated-type-bounds/fn-inline.rs
+++ b/src/test/ui/associated-type-bounds/fn-inline.rs
@@ -1,6 +1,7 @@
 // run-pass
 // aux-build:fn-aux.rs
 
+#![allow(unused)]
 #![feature(associated_type_bounds)]
 
 extern crate fn_aux;
diff --git a/src/test/ui/associated-type-bounds/fn-where.rs b/src/test/ui/associated-type-bounds/fn-where.rs
index 60d7149..9c4f82a 100644
--- a/src/test/ui/associated-type-bounds/fn-where.rs
+++ b/src/test/ui/associated-type-bounds/fn-where.rs
@@ -1,6 +1,7 @@
 // run-pass
 // aux-build:fn-aux.rs
 
+#![allow(unused)]
 #![feature(associated_type_bounds)]
 
 extern crate fn_aux;
diff --git a/src/test/ui/associated-type-bounds/fn-wrap-apit.rs b/src/test/ui/associated-type-bounds/fn-wrap-apit.rs
index 23790d4..96df13e3 100644
--- a/src/test/ui/associated-type-bounds/fn-wrap-apit.rs
+++ b/src/test/ui/associated-type-bounds/fn-wrap-apit.rs
@@ -2,6 +2,7 @@
 // aux-build:fn-aux.rs
 
 #![feature(associated_type_bounds)]
+#![allow(dead_code)]
 
 extern crate fn_aux;
 
diff --git a/src/test/ui/associated-type-bounds/inside-adt.rs b/src/test/ui/associated-type-bounds/inside-adt.rs
index 83a6082..59ce949 100644
--- a/src/test/ui/associated-type-bounds/inside-adt.rs
+++ b/src/test/ui/associated-type-bounds/inside-adt.rs
@@ -31,3 +31,5 @@
 union U3 { f: dyn Iterator<Item: 'static> }
 //~^ ERROR associated type bounds are not allowed within structs, enums, or unions
 //~| ERROR could not find defining uses
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/inside-adt.stderr b/src/test/ui/associated-type-bounds/inside-adt.stderr
index d0e0cec..9c4d03e 100644
--- a/src/test/ui/associated-type-bounds/inside-adt.stderr
+++ b/src/test/ui/associated-type-bounds/inside-adt.stderr
@@ -52,10 +52,6 @@
 LL | union U3 { f: dyn Iterator<Item: 'static> }
    |                            ^^^^^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `inside_adt`
-   |
-   = note: consider adding a `main` function to `$DIR/inside-adt.rs`
-
 error: could not find defining uses
   --> $DIR/inside-adt.rs:5:29
    |
@@ -110,6 +106,5 @@
 LL | union U3 { f: dyn Iterator<Item: 'static> }
    |                            ^^^^^^^^^^^^^
 
-error: aborting due to 19 previous errors
+error: aborting due to 18 previous errors
 
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/associated-type-bounds/struct-bounds.rs b/src/test/ui/associated-type-bounds/struct-bounds.rs
index 2d189cd..2c1ce1c 100644
--- a/src/test/ui/associated-type-bounds/struct-bounds.rs
+++ b/src/test/ui/associated-type-bounds/struct-bounds.rs
@@ -1,5 +1,6 @@
 // run-pass
 
+#![allow(unused)]
 #![feature(associated_type_bounds)]
 
 trait Tr1 { type As1; }
diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr
index 89c48d5..a304989 100644
--- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr
+++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr
@@ -1,30 +1,26 @@
 error[E0271]: type mismatch resolving `<ModelT as Vehicle>::Color == Blue`
   --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:31:10
    |
+LL | fn blue_car<C:Car<Color=Blue>>(c: C) {
+   | ------------------------------------ required by `blue_car`
+...
 LL | fn b() { blue_car(ModelT); }
    |          ^^^^^^^^ expected struct `Black`, found struct `Blue`
    |
    = note: expected type `Black`
               found type `Blue`
-note: required by `blue_car`
-  --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:27:1
-   |
-LL | fn blue_car<C:Car<Color=Blue>>(c: C) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `<ModelU as Vehicle>::Color == Black`
   --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:10
    |
+LL | fn black_car<C:Car<Color=Black>>(c: C) {
+   | -------------------------------------- required by `black_car`
+...
 LL | fn c() { black_car(ModelU); }
    |          ^^^^^^^^^ expected struct `Blue`, found struct `Black`
    |
    = note: expected type `Blue`
               found type `Black`
-note: required by `black_car`
-  --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:24:1
-   |
-LL | fn black_car<C:Car<Color=Black>>(c: C) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-bound-failure.stderr b/src/test/ui/associated-types/associated-types-bound-failure.stderr
index 502fb4f..54654b9 100644
--- a/src/test/ui/associated-types/associated-types-bound-failure.stderr
+++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `<G as GetToInt>::R: ToInt` is not satisfied
   --> $DIR/associated-types-bound-failure.rs:17:5
    |
+LL |     fn to_int(&self) -> isize;
+   |     -------------------------- required by `ToInt::to_int`
+...
 LL |     ToInt::to_int(&g.get())
    |     ^^^^^^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
    |
    = help: consider adding a `where <G as GetToInt>::R: ToInt` bound
-note: required by `ToInt::to_int`
-  --> $DIR/associated-types-bound-failure.rs:4:5
-   |
-LL |     fn to_int(&self) -> isize;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr
index 66fa4c2..0f8c525 100644
--- a/src/test/ui/associated-types/associated-types-eq-3.stderr
+++ b/src/test/ui/associated-types/associated-types-eq-3.stderr
@@ -10,16 +10,14 @@
 error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
   --> $DIR/associated-types-eq-3.rs:38:5
    |
+LL | fn foo1<I: Foo<A=Bar>>(x: I) {
+   | ---------------------------- required by `foo1`
+...
 LL |     foo1(a);
    |     ^^^^ expected usize, found struct `Bar`
    |
    = note: expected type `usize`
               found type `Bar`
-note: required by `foo1`
-  --> $DIR/associated-types-eq-3.rs:18:1
-   |
-LL | fn foo1<I: Foo<A=Bar>>(x: I) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
   --> $DIR/associated-types-eq-3.rs:41:9
diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr
index 353829c..05e6ed6 100644
--- a/src/test/ui/associated-types/associated-types-eq-hr.stderr
+++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr
@@ -1,124 +1,108 @@
 error[E0271]: type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
   --> $DIR/associated-types-eq-hr.rs:82:5
    |
-LL |     foo::<UintStruct>();
-   |     ^^^^^^^^^^^^^^^^^ expected usize, found isize
-   |
-   = note: expected type `&usize`
-              found type `&isize`
-note: required by `foo`
-  --> $DIR/associated-types-eq-hr.rs:44:1
-   |
 LL | / fn foo<T>()
 LL | |     where T : for<'x> TheTrait<&'x isize, A = &'x isize>
 LL | | {
 LL | |     // ok for IntStruct, but not UintStruct
 LL | | }
-   | |_^
+   | |_- required by `foo`
+...
+LL |       foo::<UintStruct>();
+   |       ^^^^^^^^^^^^^^^^^ expected usize, found isize
+   |
+   = note: expected type `&usize`
+              found type `&isize`
 
 error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
   --> $DIR/associated-types-eq-hr.rs:86:5
    |
-LL |     bar::<IntStruct>();
-   |     ^^^^^^^^^^^^^^^^ expected isize, found usize
-   |
-   = note: expected type `&isize`
-              found type `&usize`
-note: required by `bar`
-  --> $DIR/associated-types-eq-hr.rs:50:1
-   |
 LL | / fn bar<T>()
 LL | |     where T : for<'x> TheTrait<&'x isize, A = &'x usize>
 LL | | {
 LL | |     // ok for UintStruct, but not IntStruct
 LL | | }
-   | |_^
+   | |_- required by `bar`
+...
+LL |       bar::<IntStruct>();
+   |       ^^^^^^^^^^^^^^^^ expected isize, found usize
+   |
+   = note: expected type `&isize`
+              found type `&usize`
 
 error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
   --> $DIR/associated-types-eq-hr.rs:91:5
    |
-LL |     tuple_one::<Tuple>();
-   |     ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
-   |
-   = help: the following implementations were found:
-             <Tuple as TheTrait<(&'a isize, &'a isize)>>
-note: required by `tuple_one`
-  --> $DIR/associated-types-eq-hr.rs:56:1
-   |
 LL | / fn tuple_one<T>()
 LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
 LL | | {
 LL | |     // not ok for tuple, two lifetimes and we pick first
 LL | | }
-   | |_^
+   | |_- required by `tuple_one`
+...
+LL |       tuple_one::<Tuple>();
+   |       ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
+   |
+   = help: the following implementations were found:
+             <Tuple as TheTrait<(&'a isize, &'a isize)>>
 
 error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'x isize`
   --> $DIR/associated-types-eq-hr.rs:91:5
    |
-LL |     tuple_one::<Tuple>();
-   |     ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
-   |
-note: required by `tuple_one`
-  --> $DIR/associated-types-eq-hr.rs:56:1
-   |
 LL | / fn tuple_one<T>()
 LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
 LL | | {
 LL | |     // not ok for tuple, two lifetimes and we pick first
 LL | | }
-   | |_^
+   | |_- required by `tuple_one`
+...
+LL |       tuple_one::<Tuple>();
+   |       ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
 
 error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
   --> $DIR/associated-types-eq-hr.rs:97:5
    |
-LL |     tuple_two::<Tuple>();
-   |     ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
-   |
-   = help: the following implementations were found:
-             <Tuple as TheTrait<(&'a isize, &'a isize)>>
-note: required by `tuple_two`
-  --> $DIR/associated-types-eq-hr.rs:62:1
-   |
 LL | / fn tuple_two<T>()
 LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
 LL | | {
 LL | |     // not ok for tuple, two lifetimes and we pick second
 LL | | }
-   | |_^
+   | |_- required by `tuple_two`
+...
+LL |       tuple_two::<Tuple>();
+   |       ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
+   |
+   = help: the following implementations were found:
+             <Tuple as TheTrait<(&'a isize, &'a isize)>>
 
 error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'y isize`
   --> $DIR/associated-types-eq-hr.rs:97:5
    |
-LL |     tuple_two::<Tuple>();
-   |     ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
-   |
-note: required by `tuple_two`
-  --> $DIR/associated-types-eq-hr.rs:62:1
-   |
 LL | / fn tuple_two<T>()
 LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
 LL | | {
 LL | |     // not ok for tuple, two lifetimes and we pick second
 LL | | }
-   | |_^
+   | |_- required by `tuple_two`
+...
+LL |       tuple_two::<Tuple>();
+   |       ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
 
 error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
   --> $DIR/associated-types-eq-hr.rs:107:5
    |
-LL |     tuple_four::<Tuple>();
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
-   |
-   = help: the following implementations were found:
-             <Tuple as TheTrait<(&'a isize, &'a isize)>>
-note: required by `tuple_four`
-  --> $DIR/associated-types-eq-hr.rs:74:1
-   |
 LL | / fn tuple_four<T>()
 LL | |     where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)>
 LL | | {
 LL | |     // not ok for tuple, two lifetimes, and lifetime matching is invariant
 LL | | }
-   | |_^
+   | |_- required by `tuple_four`
+...
+LL |       tuple_four::<Tuple>();
+   |       ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
+   |
+   = help: the following implementations were found:
+             <Tuple as TheTrait<(&'a isize, &'a isize)>>
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr
index 7d5b16c..7d6c025 100644
--- a/src/test/ui/associated-types/associated-types-issue-20346.stderr
+++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr
@@ -1,16 +1,14 @@
 error[E0271]: type mismatch resolving `<Adapter<I> as Iterator>::Item == std::option::Option<T>`
   --> $DIR/associated-types-issue-20346.rs:34:5
    |
+LL | fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
+   | ------------------------------------------------ required by `is_iterator_of`
+...
 LL |     is_iterator_of::<Option<T>, _>(&adapter);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found enum `std::option::Option`
    |
    = note: expected type `T`
               found type `std::option::Option<T>`
-note: required by `is_iterator_of`
-  --> $DIR/associated-types-issue-20346.rs:15:1
-   |
-LL | fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr
index 2926bda..4a2a6d0 100644
--- a/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr
+++ b/src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr
@@ -3,28 +3,24 @@
    |
 LL |     want_y(t);
    |     ^^^^^^ expected associated type, found i32
+...
+LL | fn want_y<T:Foo<Y=i32>>(t: &T) { }
+   | ------------------------------ required by `want_y`
    |
    = note: expected type `<T as Foo>::Y`
               found type `i32`
-note: required by `want_y`
-  --> $DIR/associated-types-multiple-types-one-trait.rs:44:1
-   |
-LL | fn want_y<T:Foo<Y=i32>>(t: &T) { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `<T as Foo>::X == u32`
   --> $DIR/associated-types-multiple-types-one-trait.rs:18:5
    |
 LL |     want_x(t);
    |     ^^^^^^ expected associated type, found u32
+...
+LL | fn want_x<T:Foo<X=u32>>(t: &T) { }
+   | ------------------------------ required by `want_x`
    |
    = note: expected type `<T as Foo>::X`
               found type `u32`
-note: required by `want_x`
-  --> $DIR/associated-types-multiple-types-one-trait.rs:42:1
-   |
-LL | fn want_x<T:Foo<X=u32>>(t: &T) { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
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 a26ee23..a723854 100644
--- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr
+++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr
@@ -1,14 +1,10 @@
 error[E0284]: type annotations required: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
   --> $DIR/associated-types-overridden-binding.rs:4:1
    |
+LL | trait Foo: Iterator<Item = i32> {}
+   | ------------------------------- required by `Foo`
 LL | trait Bar: Foo<Item = u32> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: required by `Foo`
-  --> $DIR/associated-types-overridden-binding.rs:3:1
-   |
-LL | trait Foo: Iterator<Item = i32> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr
index 1405cb1..a8fcaea 100644
--- a/src/test/ui/associated-types/associated-types-path-2.stderr
+++ b/src/test/ui/associated-types/associated-types-path-2.stderr
@@ -11,14 +11,11 @@
 error[E0277]: the trait bound `u32: Foo` is not satisfied
   --> $DIR/associated-types-path-2.rs:29:5
    |
+LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
+   | -------------------------------- required by `f1`
+...
 LL |     f1(2u32, 4u32);
    |     ^^ the trait `Foo` is not implemented for `u32`
-   |
-note: required by `f1`
-  --> $DIR/associated-types-path-2.rs:13:1
-   |
-LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
   --> $DIR/associated-types-path-2.rs:29:5
@@ -29,14 +26,11 @@
 error[E0277]: the trait bound `u32: Foo` is not satisfied
   --> $DIR/associated-types-path-2.rs:35:5
    |
+LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
+   | -------------------------------- required by `f1`
+...
 LL |     f1(2u32, 4i32);
    |     ^^ the trait `Foo` is not implemented for `u32`
-   |
-note: required by `f1`
-  --> $DIR/associated-types-path-2.rs:13:1
-   |
-LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
   --> $DIR/associated-types-path-2.rs:35:5
diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
index cc69e84..22d4488 100644
--- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
+++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
@@ -1,16 +1,13 @@
 error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _`
   --> $DIR/higher-ranked-projection.rs:25:5
    |
-LL |     foo(());
-   |     ^^^ expected bound lifetime parameter 'a, found concrete lifetime
-   |
-note: required by `foo`
-  --> $DIR/higher-ranked-projection.rs:14:1
-   |
 LL | / fn foo<U, T>(_t: T)
 LL | |     where for<'a> &'a T: Mirror<Image=U>
 LL | | {}
-   | |__^
+   | |__- required by `foo`
+...
+LL |       foo(());
+   |       ^^^ expected bound lifetime parameter 'a, found concrete lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/argument-patterns.rs b/src/test/ui/async-await/argument-patterns.rs
index 0e42f48..b9fc1a8 100644
--- a/src/test/ui/async-await/argument-patterns.rs
+++ b/src/test/ui/async-await/argument-patterns.rs
@@ -1,7 +1,6 @@
 // edition:2018
-// run-pass
+// check-pass
 
-#![allow(unused_variables)]
 #![deny(unused_mut)]
 
 type A = Vec<u32>;
diff --git a/src/test/ui/async-await/async-await.rs b/src/test/ui/async-await/async-await.rs
index bf8bf0b..1dc7315 100644
--- a/src/test/ui/async-await/async-await.rs
+++ b/src/test/ui/async-await/async-await.rs
@@ -1,5 +1,7 @@
 // run-pass
 
+#![allow(unused)]
+
 // edition:2018
 // aux-build:arc_wake.rs
 
diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr
index 6b4fff2..d2f92f0 100644
--- a/src/test/ui/async-await/async-fn-nonsend.stderr
+++ b/src/test/ui/async-await/async-fn-nonsend.stderr
@@ -1,44 +1,43 @@
 error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
   --> $DIR/async-fn-nonsend.rs:50:5
    |
+LL | fn assert_send(_: impl Send) {}
+   | ---------------------------- required by `assert_send`
+...
 LL |     assert_send(local_dropped_before_await());
    |     ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
    |
    = 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, ()}`
-   = 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, ()}]`
-   = 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, ()}]>`
+   = note: required because it appears within the type `{impl std::fmt::Debug, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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: required by `assert_send`
-  --> $DIR/async-fn-nonsend.rs:47:1
-   |
-LL | fn assert_send(_: impl Send) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
   --> $DIR/async-fn-nonsend.rs:52:5
    |
+LL | fn assert_send(_: impl Send) {}
+   | ---------------------------- required by `assert_send`
+...
 LL |     assert_send(non_send_temporary_in_match());
    |     ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
    |
    = 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 `{fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}`
-   = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, 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 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]>`
+   = note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, fn() -> impl std::future::Future {fut}, impl std::future::Future, ()}`
+   = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, fn() -> impl std::future::Future {fut}, 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 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, fn() -> impl std::future::Future {fut}, 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: required by `assert_send`
-  --> $DIR/async-fn-nonsend.rs:47:1
-   |
-LL | fn assert_send(_: impl Send) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely
   --> $DIR/async-fn-nonsend.rs:54:5
    |
+LL | fn assert_send(_: impl Send) {}
+   | ---------------------------- required by `assert_send`
+...
 LL |     assert_send(non_sync_with_method_call());
    |     ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely
    |
@@ -46,20 +45,18 @@
    = 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, 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, 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, impl std::future::Future, ()}]>`
+   = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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: required by `assert_send`
-  --> $DIR/async-fn-nonsend.rs:47:1
-   |
-LL | fn assert_send(_: impl Send) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
   --> $DIR/async-fn-nonsend.rs:54:5
    |
+LL | fn assert_send(_: impl Send) {}
+   | ---------------------------- required by `assert_send`
+...
 LL |     assert_send(non_sync_with_method_call());
    |     ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
    |
@@ -71,16 +68,11 @@
    = 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, 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, 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, impl std::future::Future, ()}]>`
+   = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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, fn() -> impl std::future::Future {fut}, 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: required by `assert_send`
-  --> $DIR/async-fn-nonsend.rs:47:1
-   |
-LL | fn assert_send(_: impl Send) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs b/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs
index 5d020c9..15cc9fb 100644
--- a/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs
+++ b/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs
@@ -3,6 +3,9 @@
 // run-pass
 
 #![deny(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_must_use)]
+#![allow(path_statements)]
 
 // Test that the drop order for locals in a fn and async fn matches up.
 extern crate arc_wake;
@@ -10,7 +13,6 @@
 use arc_wake::ArcWake;
 use std::cell::RefCell;
 use std::future::Future;
-use std::marker::PhantomData;
 use std::pin::Pin;
 use std::rc::Rc;
 use std::sync::Arc;
@@ -42,7 +44,7 @@
 
 impl Future for NeverReady {
     type Output = ();
-    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
         Poll::Pending
     }
 }
diff --git a/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
new file mode 100644
index 0000000..e40acff
--- /dev/null
+++ b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
@@ -0,0 +1,95 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+#![allow(unused_variables)]
+
+// Test the drop order for parameters relative to local variables and
+// temporaries created in the tail return expression of the function
+// body. In particular, check that this drop order is the same between
+// a `async fn` and an ordinary `fn`. See #64512.
+
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::sync::Arc;
+use std::rc::Rc;
+use std::task::Context;
+
+struct EmptyWaker;
+
+impl ArcWake for EmptyWaker {
+    fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+    Function,
+    Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+    fn drop(&mut self) {
+        self.1.borrow_mut().push(DropOrder::Val(self.0));
+    }
+}
+
+/// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`.
+///
+/// Expected order:
+/// - `z`
+/// - temp
+/// - `y`
+/// - `x`
+async fn foo_async(x: D, _y: D) {
+    let l = x.1.clone();
+    let z = D("z", l.clone());
+    l.borrow_mut().push(DropOrder::Function);
+    helper_async(&D("temp", l)).await
+}
+
+async fn helper_async(v: &D) { }
+
+fn foo_sync(x: D, _y: D) {
+    let l = x.1.clone();
+    let z = D("z", l.clone());
+    l.borrow_mut().push(DropOrder::Function);
+    helper_sync(&D("temp", l))
+}
+
+fn helper_sync(v: &D) { }
+
+fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
+    f: impl FnOnce(DropOrderListPtr) -> Fut,
+    g: impl FnOnce(DropOrderListPtr),
+) {
+    let empty = Arc::new(EmptyWaker);
+    let waker = ArcWake::into_waker(empty);
+    let mut cx = Context::from_waker(&waker);
+
+    let actual_order = Rc::new(RefCell::new(Vec::new()));
+    let mut fut = Box::pin(f(actual_order.clone()));
+    let r = fut.as_mut().poll(&mut cx);
+
+    assert!(match r {
+        std::task::Poll::Ready(()) => true,
+        _ => false,
+    });
+
+    let expected_order = Rc::new(RefCell::new(Vec::new()));
+    g(expected_order.clone());
+
+    assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+    // Free functions (see doc comment on function for what it tests).
+    assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
+                                 |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));
+}
diff --git a/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs b/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs
index 84fe793..9e83049 100644
--- a/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs
+++ b/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs
@@ -6,6 +6,8 @@
 // parameters (used or unused) are not dropped until the async fn is cancelled.
 // This file is mostly copy-pasted from drop-order-for-async-fn-parameters.rs
 
+#![allow(unused_variables)]
+
 extern crate arc_wake;
 
 use arc_wake::ArcWake;
@@ -43,7 +45,7 @@
 
 impl Future for NeverReady {
     type Output = ();
-    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
         Poll::Pending
     }
 }
diff --git a/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs b/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs
new file mode 100644
index 0000000..54059b2
--- /dev/null
+++ b/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs
@@ -0,0 +1,19 @@
+// check-pass
+// edition:2018
+
+struct Test(String);
+
+impl Test {
+    async fn borrow_async(&self) {}
+
+    fn with(&mut self, s: &str) -> &mut Self {
+        self.0 = s.into();
+        self
+    }
+}
+
+async fn test() {
+    Test("".to_string()).with("123").borrow_async().await;
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime.rs b/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime.rs
new file mode 100644
index 0000000..c5ea2b8
--- /dev/null
+++ b/src/test/ui/async-await/issue-63832-await-short-temporary-lifetime.rs
@@ -0,0 +1,12 @@
+// check-pass
+// edition:2018
+
+async fn foo(x: &[Vec<u32>]) -> u32 {
+    0
+}
+
+async fn bar() {
+    foo(&[vec![123]]).await;
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/issue-64391.rs b/src/test/ui/async-await/issue-64391.rs
new file mode 100644
index 0000000..c6faad3
--- /dev/null
+++ b/src/test/ui/async-await/issue-64391.rs
@@ -0,0 +1,14 @@
+// Regression test for Issue #64391. The goal here is that this
+// function compiles. In the past, due to incorrect drop order for
+// temporaries in the tail expression, we failed to compile this
+// example. The drop order itself is directly tested in
+// `drop-order/drop-order-for-temporary-in-tail-return-expr.rs`.
+//
+// check-pass
+// edition:2018
+
+async fn add(x: u32, y: u32) -> u32 {
+    async { x + y }.await
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/issues/issue-54752-async-block.stderr b/src/test/ui/async-await/issues/issue-54752-async-block.stderr
new file mode 100644
index 0000000..c3b3392
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-54752-async-block.stderr
@@ -0,0 +1,8 @@
+warning: unnecessary parentheses around assigned value
+  --> $DIR/issue-54752-async-block.rs:6:22
+   |
+LL | fn main() { let _a = (async  { }); }
+   |                      ^^^^^^^^^^^^ help: remove these parentheses
+   |
+   = note: `#[warn(unused_parens)]` on by default
+
diff --git a/src/test/ui/async-await/issues/issue-59972.rs b/src/test/ui/async-await/issues/issue-59972.rs
index 154226e..c2e24a9 100644
--- a/src/test/ui/async-await/issues/issue-59972.rs
+++ b/src/test/ui/async-await/issues/issue-59972.rs
@@ -4,7 +4,7 @@
 
 // run-pass
 
-// compile-flags: --edition=2018
+// compile-flags: --edition=2018 -Aunused
 
 pub enum Uninhabited { }
 
diff --git a/src/test/ui/async-await/multiple-lifetimes/hrtb.rs b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs
index 31d0736..e788ca5 100644
--- a/src/test/ui/async-await/multiple-lifetimes/hrtb.rs
+++ b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs
@@ -1,5 +1,5 @@
 // edition:2018
-// run-pass
+// check-pass
 
 // Test that we can use async fns with multiple arbitrary lifetimes.
 
diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs
new file mode 100644
index 0000000..bb2a61f
--- /dev/null
+++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs
@@ -0,0 +1,13 @@
+// edition:2018
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden when using `async` and `await`.
+
+async fn rec_1() { //~ ERROR recursion in an `async fn`
+    rec_2().await;
+}
+
+async fn rec_2() { //~ ERROR recursion in an `async fn`
+    rec_1().await;
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
new file mode 100644
index 0000000..9249308
--- /dev/null
+++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
@@ -0,0 +1,19 @@
+error[E0733]: recursion in an `async fn` requires boxing
+  --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:18
+   |
+LL | async fn rec_1() {
+   |                  ^ recursive `async fn`
+   |
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`.
+
+error[E0733]: recursion in an `async fn` requires boxing
+  --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18
+   |
+LL | async fn rec_2() {
+   |                  ^ recursive `async fn`
+   |
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`.
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.rs b/src/test/ui/async-await/no-non-guaranteed-initialization.rs
index 0afbf4c..6a34209 100644
--- a/src/test/ui/async-await/no-non-guaranteed-initialization.rs
+++ b/src/test/ui/async-await/no-non-guaranteed-initialization.rs
@@ -8,7 +8,7 @@
         y = echo(10).await;
     }
     y
-    //~^ use of possibly uninitialized variable: `y`
+    //~^ use of possibly-uninitialized variable: `y`
 }
 
 async fn echo(x: usize) -> usize { x + 1 }
diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
index 91d7994..b9aa992 100644
--- a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
+++ b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `y`
+error[E0381]: use of possibly-uninitialized variable: `y`
   --> $DIR/no-non-guaranteed-initialization.rs:10:5
    |
 LL |     y
-   |     ^ use of possibly uninitialized `y`
+   |     ^ use of possibly-uninitialized `y`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/partial-initialization-across-await.rs b/src/test/ui/async-await/partial-initialization-across-await.rs
index 1785fb7..8a98a4b 100644
--- a/src/test/ui/async-await/partial-initialization-across-await.rs
+++ b/src/test/ui/async-await/partial-initialization-across-await.rs
@@ -11,7 +11,7 @@
 async fn test_tuple() {
     let mut t: (i32, i32);
     t.0 = 42;
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
     noop().await;
     t.1 = 88;
     let _ = t;
@@ -20,7 +20,7 @@
 async fn test_tuple_struct() {
     let mut t: T;
     t.0 = 42;
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
     noop().await;
     t.1 = 88;
     let _ = t;
@@ -29,7 +29,7 @@
 async fn test_struct() {
     let mut t: S;
     t.x = 42;
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
     noop().await;
     t.y = 88;
     let _ = t;
diff --git a/src/test/ui/async-await/partial-initialization-across-await.stderr b/src/test/ui/async-await/partial-initialization-across-await.stderr
index d9a2db9..9a510c2 100644
--- a/src/test/ui/async-await/partial-initialization-across-await.stderr
+++ b/src/test/ui/async-await/partial-initialization-across-await.stderr
@@ -1,20 +1,20 @@
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/partial-initialization-across-await.rs:13:5
    |
 LL |     t.0 = 42;
-   |     ^^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/partial-initialization-across-await.rs:22:5
    |
 LL |     t.0 = 42;
-   |     ^^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/partial-initialization-across-await.rs:31:5
    |
 LL |     t.x = 42;
-   |     ^^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^^ use of possibly-uninitialized `t`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr
index 8781a9c..9ee0140 100644
--- a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr
+++ b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr
@@ -2,9 +2,9 @@
   --> $DIR/recursive-async-impl-trait-type.rs:5:40
    |
 LL | async fn recursive_async_function() -> () {
-   |                                        ^^ an `async fn` cannot invoke itself directly
+   |                                        ^^ recursive `async fn`
    |
-   = note: a recursive `async fn` must be rewritten to return a boxed future.
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/attributes/item-attributes.rs b/src/test/ui/attributes/item-attributes.rs
index c760a28..79cd0f5 100644
--- a/src/test/ui/attributes/item-attributes.rs
+++ b/src/test/ui/attributes/item-attributes.rs
@@ -11,8 +11,6 @@
 #![rustc_dummy]
 #![rustc_dummy(attr5)]
 
-#![crate_id="foobar#0.1"]
-
 // These are attributes of the following mod
 #[rustc_dummy = "val"]
 #[rustc_dummy = "val"]
diff --git a/src/test/ui/attributes/obsolete-attr.rs b/src/test/ui/attributes/obsolete-attr.rs
index 8759344..42f90ed 100644
--- a/src/test/ui/attributes/obsolete-attr.rs
+++ b/src/test/ui/attributes/obsolete-attr.rs
@@ -1,9 +1,9 @@
-// Obsolete attributes fall back to feature gated custom attributes.
+// Obsolete attributes fall back to unstable custom attributes.
 
 #[ab_isize="stdcall"] extern {}
-//~^ ERROR cannot find attribute macro `ab_isize` in this scope
+//~^ ERROR cannot find attribute `ab_isize` in this scope
 
 #[fixed_stack_segment] fn f() {}
-//~^ ERROR cannot find attribute macro `fixed_stack_segment` in this scope
+//~^ ERROR cannot find attribute `fixed_stack_segment` in this scope
 
 fn main() {}
diff --git a/src/test/ui/attributes/obsolete-attr.stderr b/src/test/ui/attributes/obsolete-attr.stderr
index 9c6909f..2d7c257 100644
--- a/src/test/ui/attributes/obsolete-attr.stderr
+++ b/src/test/ui/attributes/obsolete-attr.stderr
@@ -1,10 +1,10 @@
-error: cannot find attribute macro `fixed_stack_segment` in this scope
+error: cannot find attribute `fixed_stack_segment` in this scope
   --> $DIR/obsolete-attr.rs:6:3
    |
 LL | #[fixed_stack_segment] fn f() {}
    |   ^^^^^^^^^^^^^^^^^^^
 
-error: cannot find attribute macro `ab_isize` in this scope
+error: cannot find attribute `ab_isize` in this scope
   --> $DIR/obsolete-attr.rs:3:3
    |
 LL | #[ab_isize="stdcall"] extern {}
diff --git a/src/test/ui/attributes/unknown-attr.rs b/src/test/ui/attributes/unknown-attr.rs
index 140a1fc..70fef04 100644
--- a/src/test/ui/attributes/unknown-attr.rs
+++ b/src/test/ui/attributes/unknown-attr.rs
@@ -1,12 +1,12 @@
-// Unknown attributes fall back to feature gated custom attributes.
+// Unknown attributes fall back to unstable custom attributes.
 
 #![feature(custom_inner_attributes)]
 
 #![mutable_doc]
-//~^ ERROR cannot find attribute macro `mutable_doc` in this scope
+//~^ ERROR cannot find attribute `mutable_doc` in this scope
 
 #[dance] mod a {}
-//~^ ERROR cannot find attribute macro `dance` in this scope
+//~^ ERROR cannot find attribute `dance` in this scope
 
 #[dance] fn main() {}
-//~^ ERROR cannot find attribute macro `dance` in this scope
+//~^ ERROR cannot find attribute `dance` in this scope
diff --git a/src/test/ui/attributes/unknown-attr.stderr b/src/test/ui/attributes/unknown-attr.stderr
index 4d46387..85c227d 100644
--- a/src/test/ui/attributes/unknown-attr.stderr
+++ b/src/test/ui/attributes/unknown-attr.stderr
@@ -1,16 +1,16 @@
-error: cannot find attribute macro `mutable_doc` in this scope
+error: cannot find attribute `mutable_doc` in this scope
   --> $DIR/unknown-attr.rs:5:4
    |
 LL | #![mutable_doc]
    |    ^^^^^^^^^^^
 
-error: cannot find attribute macro `dance` in this scope
+error: cannot find attribute `dance` in this scope
   --> $DIR/unknown-attr.rs:8:3
    |
 LL | #[dance] mod a {}
    |   ^^^^^
 
-error: cannot find attribute macro `dance` in this scope
+error: cannot find attribute `dance` in this scope
   --> $DIR/unknown-attr.rs:11:3
    |
 LL | #[dance] fn main() {}
diff --git a/src/test/ui/attributes/unnamed-field-attributes.rs b/src/test/ui/attributes/unnamed-field-attributes.rs
new file mode 100644
index 0000000..93f3640
--- /dev/null
+++ b/src/test/ui/attributes/unnamed-field-attributes.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+struct S(
+    #[rustfmt::skip] u8,
+    u16,
+    #[rustfmt::skip] u32,
+);
+
+fn main() {}
diff --git a/src/test/ui/attrs-resolution-errors.rs b/src/test/ui/attrs-resolution-errors.rs
new file mode 100644
index 0000000..a38b3cf
--- /dev/null
+++ b/src/test/ui/attrs-resolution-errors.rs
@@ -0,0 +1,40 @@
+enum FooEnum {
+    #[test]
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    Bar(i32),
+}
+
+struct FooStruct {
+    #[test]
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    bar: i32,
+}
+
+fn main() {
+    let foo_enum_bar = FooEnum::Bar(1);
+    match foo_enum_bar {
+        FooEnum::Bar(x) => {},
+        _ => {}
+    }
+
+    let foo_struct = FooStruct { bar: 1 };
+    match foo_struct {
+        FooStruct {
+            #[test] bar
+            //~^ ERROR expected an inert attribute, found an attribute macro
+        } => {}
+    }
+
+    match 1 {
+        0 => {}
+        #[test]
+        //~^ ERROR expected an inert attribute, found an attribute macro
+        _ => {}
+    }
+
+    let _another_foo_strunct = FooStruct {
+        #[test]
+        //~^ ERROR expected an inert attribute, found an attribute macro
+        bar: 1,
+    };
+}
diff --git a/src/test/ui/attrs-resolution-errors.stderr b/src/test/ui/attrs-resolution-errors.stderr
new file mode 100644
index 0000000..31f2a74
--- /dev/null
+++ b/src/test/ui/attrs-resolution-errors.stderr
@@ -0,0 +1,32 @@
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/attrs-resolution-errors.rs:2:5
+   |
+LL |     #[test]
+   |     ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/attrs-resolution-errors.rs:8:5
+   |
+LL |     #[test]
+   |     ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/attrs-resolution-errors.rs:23:13
+   |
+LL |             #[test] bar
+   |             ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/attrs-resolution-errors.rs:30:9
+   |
+LL |         #[test]
+   |         ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/attrs-resolution-errors.rs:36:9
+   |
+LL |         #[test]
+   |         ^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/attrs-resolution.rs b/src/test/ui/attrs-resolution.rs
new file mode 100644
index 0000000..6809773
--- /dev/null
+++ b/src/test/ui/attrs-resolution.rs
@@ -0,0 +1,37 @@
+// check-pass
+
+enum FooEnum {
+    #[rustfmt::skip]
+    Bar(i32),
+}
+
+struct FooStruct {
+    #[rustfmt::skip]
+    bar: i32,
+}
+
+fn main() {
+    let foo_enum_bar = FooEnum::Bar(1);
+    match foo_enum_bar {
+        FooEnum::Bar(x) => {}
+        _ => {}
+    }
+
+    let foo_struct = FooStruct { bar: 1 };
+    match foo_struct {
+        FooStruct {
+            #[rustfmt::skip] bar
+        } => {}
+    }
+
+    match 1 {
+        0 => {}
+        #[rustfmt::skip]
+        _ => {}
+    }
+
+    let _another_foo_strunct = FooStruct {
+        #[rustfmt::skip]
+        bar: 1,
+    };
+}
diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr
index f2e0d37..3e36f24 100644
--- a/src/test/ui/auto-ref-slice-plus-ref.stderr
+++ b/src/test/ui/auto-ref-slice-plus-ref.stderr
@@ -12,7 +12,7 @@
   --> $DIR/auto-ref-slice-plus-ref.rs:8:7
    |
 LL |     a.test();
-   |       ^^^^
+   |       ^^^^ method not found in `std::vec::Vec<{integer}>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `test`, perhaps you need to implement it:
@@ -22,7 +22,7 @@
   --> $DIR/auto-ref-slice-plus-ref.rs:10:11
    |
 LL |     ([1]).test();
-   |           ^^^^
+   |           ^^^^ method not found in `[{integer}; 1]`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `test`, perhaps you need to implement it:
@@ -32,7 +32,7 @@
   --> $DIR/auto-ref-slice-plus-ref.rs:11:12
    |
 LL |     (&[1]).test();
-   |            ^^^^
+   |            ^^^^ method not found in `&[{integer}; 1]`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `test`, perhaps you need to implement it:
diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.rs b/src/test/ui/bind-by-move/bind-by-move-no-guards.rs
deleted file mode 100644
index bc9b3a8..0000000
--- a/src/test/ui/bind-by-move/bind-by-move-no-guards.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-use std::sync::mpsc::channel;
-
-fn main() {
-    let (tx, rx) = channel();
-    let x = Some(rx);
-    tx.send(false);
-    match x {
-        Some(z) if z.recv().unwrap() => { panic!() },
-            //~^ ERROR cannot bind by-move into a pattern guard
-        Some(z) => { assert!(!z.recv().unwrap()); },
-        None => panic!()
-    }
-}
diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr b/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr
deleted file mode 100644
index c5f0256..0000000
--- a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0008]: cannot bind by-move into a pattern guard
-  --> $DIR/bind-by-move-no-guards.rs:8:14
-   |
-LL |         Some(z) if z.recv().unwrap() => { panic!() },
-   |              ^ moves value into pattern guard
-   |
-   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/borrowck/assign_mutable_fields.stderr b/src/test/ui/borrowck/assign_mutable_fields.stderr
index 35101df..40f1aae 100644
--- a/src/test/ui/borrowck/assign_mutable_fields.stderr
+++ b/src/test/ui/borrowck/assign_mutable_fields.stderr
@@ -1,14 +1,14 @@
-error[E0381]: assign to part of possibly uninitialized variable: `x`
+error[E0381]: assign to part of possibly-uninitialized variable: `x`
   --> $DIR/assign_mutable_fields.rs:9:5
    |
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: assign to part of possibly uninitialized variable: `x`
+error[E0381]: assign to part of possibly-uninitialized variable: `x`
   --> $DIR/assign_mutable_fields.rs:17:5
    |
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-and-init.rs b/src/test/ui/borrowck/borrowck-and-init.rs
index 4427e25..f11d44e 100644
--- a/src/test/ui/borrowck/borrowck-and-init.rs
+++ b/src/test/ui/borrowck/borrowck-and-init.rs
@@ -2,5 +2,5 @@
     let i: isize;
 
     println!("{}", false && { i = 5; true });
-    println!("{}", i); //~ ERROR borrow of possibly uninitialized variable: `i`
+    println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i`
 }
diff --git a/src/test/ui/borrowck/borrowck-and-init.stderr b/src/test/ui/borrowck/borrowck-and-init.stderr
index 2db0751..c7e357d 100644
--- a/src/test/ui/borrowck/borrowck-and-init.stderr
+++ b/src/test/ui/borrowck/borrowck-and-init.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `i`
+error[E0381]: borrow of possibly-uninitialized variable: `i`
   --> $DIR/borrowck-and-init.rs:5:20
    |
 LL |     println!("{}", i);
-   |                    ^ use of possibly uninitialized `i`
+   |                    ^ use of possibly-uninitialized `i`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-asm.rs b/src/test/ui/borrowck/borrowck-asm.rs
index 9c9cc04..c1b0f39 100644
--- a/src/test/ui/borrowck/borrowck-asm.rs
+++ b/src/test/ui/borrowck/borrowck-asm.rs
@@ -57,7 +57,7 @@
     fn indirect_is_not_init() {
         let x: i32;
         unsafe {
-            asm!("nop" : "=*r"(x)); //~ ERROR use of possibly uninitialized variable
+            asm!("nop" : "=*r"(x)); //~ ERROR use of possibly-uninitialized variable
         }
     }
 
diff --git a/src/test/ui/borrowck/borrowck-asm.stderr b/src/test/ui/borrowck/borrowck-asm.stderr
index c771373..f85b598 100644
--- a/src/test/ui/borrowck/borrowck-asm.stderr
+++ b/src/test/ui/borrowck/borrowck-asm.stderr
@@ -46,11 +46,11 @@
 LL |             asm!("nop" : "+r"(x));
    |                               ^ cannot assign twice to immutable variable
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-asm.rs:60:32
    |
 LL |             asm!("nop" : "=*r"(x));
-   |                                ^ use of possibly uninitialized `x`
+   |                                ^ use of possibly-uninitialized `x`
 
 error[E0506]: cannot assign to `x` because it is borrowed
   --> $DIR/borrowck-asm.rs:68:31
diff --git a/src/test/ui/borrowck/borrowck-block-unint.rs b/src/test/ui/borrowck/borrowck-block-unint.rs
index 1fed2d5..1e7306a 100644
--- a/src/test/ui/borrowck/borrowck-block-unint.rs
+++ b/src/test/ui/borrowck/borrowck-block-unint.rs
@@ -1,7 +1,7 @@
 fn force<F>(f: F) where F: FnOnce() { f(); }
 fn main() {
     let x: isize;
-    force(|| {  //~ ERROR borrow of possibly uninitialized variable: `x`
+    force(|| {  //~ ERROR borrow of possibly-uninitialized variable: `x`
         println!("{}", x);
     });
 }
diff --git a/src/test/ui/borrowck/borrowck-block-unint.stderr b/src/test/ui/borrowck/borrowck-block-unint.stderr
index d2a4996..578f89d 100644
--- a/src/test/ui/borrowck/borrowck-block-unint.stderr
+++ b/src/test/ui/borrowck/borrowck-block-unint.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-block-unint.rs:4:11
    |
 LL |     force(|| {
-   |           ^^ use of possibly uninitialized `x`
+   |           ^^ use of possibly-uninitialized `x`
 LL |         println!("{}", x);
    |                        - borrow occurs due to use in closure
 
diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.rs b/src/test/ui/borrowck/borrowck-break-uninit-2.rs
index dad5325..126d991 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit-2.rs
+++ b/src/test/ui/borrowck/borrowck-break-uninit-2.rs
@@ -6,7 +6,7 @@
         x = 0;
     }
 
-    println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x`
+    println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x`
 
     return 17;
 }
diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
index e40d8d9..bc9b25c 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
+++ b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-break-uninit-2.rs:9:20
    |
 LL |     println!("{}", x);
-   |                    ^ use of possibly uninitialized `x`
+   |                    ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-break-uninit.rs b/src/test/ui/borrowck/borrowck-break-uninit.rs
index 9af02b3..8ccb21a 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit.rs
+++ b/src/test/ui/borrowck/borrowck-break-uninit.rs
@@ -6,7 +6,7 @@
         x = 0;
     }
 
-    println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x`
+    println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x`
 
     return 17;
 }
diff --git a/src/test/ui/borrowck/borrowck-break-uninit.stderr b/src/test/ui/borrowck/borrowck-break-uninit.stderr
index bbf9b9f..766d5cf 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit.stderr
+++ b/src/test/ui/borrowck/borrowck-break-uninit.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-break-uninit.rs:9:20
    |
 LL |     println!("{}", x);
-   |                    ^ use of possibly uninitialized `x`
+   |                    ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.rs b/src/test/ui/borrowck/borrowck-field-sensitivity.rs
index 88f74d1..ab607c2 100644
--- a/src/test/ui/borrowck/borrowck-field-sensitivity.rs
+++ b/src/test/ui/borrowck/borrowck-field-sensitivity.rs
@@ -78,20 +78,20 @@
 
 fn copy_after_field_assign_after_uninit() {
     let mut x: A;
-    x.a = 1; //~ ERROR assign to part of possibly uninitialized variable: `x`
+    x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x`
     drop(x.a);
 }
 
 fn borrow_after_field_assign_after_uninit() {
     let mut x: A;
-    x.a = 1; //~ ERROR assign to part of possibly uninitialized variable: `x`
+    x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x`
     let p = &x.a;
     drop(*p);
 }
 
 fn move_after_field_assign_after_uninit() {
     let mut x: A;
-    x.b = box 1; //~ ERROR assign to part of possibly uninitialized variable: `x`
+    x.b = box 1; //~ ERROR assign to part of possibly-uninitialized variable: `x`
     drop(x.b);
 }
 
diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
index 8952323..158b2e4 100644
--- a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
+++ b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
@@ -108,23 +108,23 @@
    |
    = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
 
-error[E0381]: assign to part of possibly uninitialized variable: `x`
+error[E0381]: assign to part of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-field-sensitivity.rs:81:5
    |
 LL |     x.a = 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: assign to part of possibly uninitialized variable: `x`
+error[E0381]: assign to part of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-field-sensitivity.rs:87:5
    |
 LL |     x.a = 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: assign to part of possibly uninitialized variable: `x`
+error[E0381]: assign to part of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-field-sensitivity.rs:94:5
    |
 LL |     x.b = box 1;
-   |     ^^^ use of possibly uninitialized `x`
+   |     ^^^ use of possibly-uninitialized `x`
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-if-no-else.rs b/src/test/ui/borrowck/borrowck-if-no-else.rs
index 044db99..f59bcad 100644
--- a/src/test/ui/borrowck/borrowck-if-no-else.rs
+++ b/src/test/ui/borrowck/borrowck-if-no-else.rs
@@ -2,5 +2,5 @@
 
 fn main() {
     let x: isize; if 1 > 2 { x = 10; }
-    foo(x); //~ ERROR use of possibly uninitialized variable: `x`
+    foo(x); //~ ERROR use of possibly-uninitialized variable: `x`
 }
diff --git a/src/test/ui/borrowck/borrowck-if-no-else.stderr b/src/test/ui/borrowck/borrowck-if-no-else.stderr
index 1223e40..3e9d3d4 100644
--- a/src/test/ui/borrowck/borrowck-if-no-else.stderr
+++ b/src/test/ui/borrowck/borrowck-if-no-else.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-if-no-else.rs:5:9
    |
 LL |     foo(x);
-   |         ^ use of possibly uninitialized `x`
+   |         ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-if-with-else.rs b/src/test/ui/borrowck/borrowck-if-with-else.rs
index f632d61..c13318b 100644
--- a/src/test/ui/borrowck/borrowck-if-with-else.rs
+++ b/src/test/ui/borrowck/borrowck-if-with-else.rs
@@ -7,5 +7,5 @@
     } else {
         x = 10;
     }
-    foo(x); //~ ERROR use of possibly uninitialized variable: `x`
+    foo(x); //~ ERROR use of possibly-uninitialized variable: `x`
 }
diff --git a/src/test/ui/borrowck/borrowck-if-with-else.stderr b/src/test/ui/borrowck/borrowck-if-with-else.stderr
index d11f29b..53b8a6b 100644
--- a/src/test/ui/borrowck/borrowck-if-with-else.stderr
+++ b/src/test/ui/borrowck/borrowck-if-with-else.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-if-with-else.rs:10:9
    |
 LL |     foo(x);
-   |         ^ use of possibly uninitialized `x`
+   |         ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs
index f745778..9905e42 100644
--- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs
+++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs
@@ -1,7 +1,7 @@
 fn main() {
     let j = || -> isize {
         let i: isize;
-        i //~ ERROR use of possibly uninitialized variable: `i`
+        i //~ ERROR use of possibly-uninitialized variable: `i`
     };
     j();
 }
diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
index 82a602c..2d1d9bc 100644
--- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `i`
+error[E0381]: use of possibly-uninitialized variable: `i`
   --> $DIR/borrowck-init-in-called-fn-expr.rs:4:9
    |
 LL |         i
-   |         ^ use of possibly uninitialized `i`
+   |         ^ use of possibly-uninitialized `i`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs
index 5055814..7dd3396 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs
+++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs
@@ -1,7 +1,7 @@
 fn main() {
     let f  = || -> isize {
         let i: isize;
-        i //~ ERROR use of possibly uninitialized variable: `i`
+        i //~ ERROR use of possibly-uninitialized variable: `i`
     };
     println!("{}", f());
 }
diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
index 8997393..fd8b90e 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `i`
+error[E0381]: use of possibly-uninitialized variable: `i`
   --> $DIR/borrowck-init-in-fn-expr.rs:4:9
    |
 LL |         i
-   |         ^ use of possibly uninitialized `i`
+   |         ^ use of possibly-uninitialized `i`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.rs b/src/test/ui/borrowck/borrowck-init-in-fru.rs
index 6da3098d..d7ec2ed 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fru.rs
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.rs
@@ -7,6 +7,6 @@
 fn main() {
     let mut origin: Point;
     origin = Point { x: 10, ..origin };
-    //~^ ERROR use of possibly uninitialized variable: `origin` [E0381]
+    //~^ ERROR use of possibly-uninitialized variable: `origin` [E0381]
     origin.clone();
 }
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
index fe55bc2..a4c042d 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fru.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `origin`
+error[E0381]: use of possibly-uninitialized variable: `origin`
   --> $DIR/borrowck-init-in-fru.rs:9:5
    |
 LL |     origin = Point { x: 10, ..origin };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `origin.y`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `origin.y`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.rs b/src/test/ui/borrowck/borrowck-init-op-equal.rs
index d3fa852..784eb8c 100644
--- a/src/test/ui/borrowck/borrowck-init-op-equal.rs
+++ b/src/test/ui/borrowck/borrowck-init-op-equal.rs
@@ -1,6 +1,6 @@
 fn test() {
     let v: isize;
-    v += 1; //~ ERROR use of possibly uninitialized variable: `v`
+    v += 1; //~ ERROR use of possibly-uninitialized variable: `v`
     v.clone();
 }
 
diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.stderr b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
index 9863ceb..6c88778 100644
--- a/src/test/ui/borrowck/borrowck-init-op-equal.stderr
+++ b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `v`
+error[E0381]: use of possibly-uninitialized variable: `v`
   --> $DIR/borrowck-init-op-equal.rs:3:5
    |
 LL |     v += 1;
-   |     ^^^^^^ use of possibly uninitialized `v`
+   |     ^^^^^^ use of possibly-uninitialized `v`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.rs b/src/test/ui/borrowck/borrowck-init-plus-equal.rs
index d895a2e..d9d20a2 100644
--- a/src/test/ui/borrowck/borrowck-init-plus-equal.rs
+++ b/src/test/ui/borrowck/borrowck-init-plus-equal.rs
@@ -1,6 +1,6 @@
 fn test() {
     let mut v: isize;
-    v = v + 1; //~ ERROR use of possibly uninitialized variable: `v`
+    v = v + 1; //~ ERROR use of possibly-uninitialized variable: `v`
     v.clone();
 }
 
diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
index 80c4e0c..fe09c85 100644
--- a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
+++ b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `v`
+error[E0381]: use of possibly-uninitialized variable: `v`
   --> $DIR/borrowck-init-plus-equal.rs:3:9
    |
 LL |     v = v + 1;
-   |         ^ use of possibly uninitialized `v`
+   |         ^ use of possibly-uninitialized `v`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
index a33a1d0..58f2cad 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
@@ -1,15 +1,14 @@
-warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-migrate-to-nll.rs:28:21
+error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-migrate-to-nll.rs:29:21
    |
 LL |     let x = &mut block;
    |             ---------- mutable borrow occurs here
 LL |     let p: &'a u8 = &*block.current;
    |                     ^^^^^^^^^^^^^^^ immutable borrow occurs here
-LL |     // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes)
+...
 LL |     drop(x);
    |          - mutable borrow later used here
-   |
-   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
-   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
-   = note: for more information, try `rustc --explain E0729`
 
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
index 6dda317..6587dfd 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.rs
@@ -4,6 +4,8 @@
 //
 // Therefore, for backwards-compatiblity, under borrowck=migrate the
 // NLL checks will be emitted as *warnings*.
+//
+// In Rust 2018, no errors will be downgraded to warnings.
 
 // NLL mode makes this compile-fail; we cannot currently encode a
 // test that is run-pass or compile-fail based on compare-mode. So
@@ -15,8 +17,7 @@
 // revisions: zflag edition
 //[zflag]compile-flags: -Z borrowck=migrate
 //[edition]edition:2018
-//[zflag] run-pass
-//[edition] run-pass
+//[zflag] check-pass
 
 pub struct Block<'a> {
     current: &'a u8,
@@ -26,6 +27,7 @@
 fn bump<'a>(mut block: &mut Block<'a>) {
     let x = &mut block;
     let p: &'a u8 = &*block.current;
+    //[edition]~^ ERROR cannot borrow `*block.current` as immutable
     // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes)
     drop(x);
     drop(p);
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
index a33a1d0..ace336a 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
@@ -1,11 +1,11 @@
 warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-migrate-to-nll.rs:28:21
+  --> $DIR/borrowck-migrate-to-nll.rs:29:21
    |
 LL |     let x = &mut block;
    |             ---------- mutable borrow occurs here
 LL |     let p: &'a u8 = &*block.current;
    |                     ^^^^^^^^^^^^^^^ immutable borrow occurs here
-LL |     // (use `x` and `p` so enabling NLL doesn't assign overly short lifetimes)
+...
 LL |     drop(x);
    |          - mutable borrow later used here
    |
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
index 5b6aa7a..9cbceeb 100644
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
@@ -8,12 +8,9 @@
     let mut x = Enum::A(&mut n);
     match x {
         Enum::A(_) if { x = Enum::B(false); false } => 1,
-        //~^ ERROR cannot assign in a pattern guard
-        //~| ERROR cannot assign `x` in match guard
+        //~^ ERROR cannot assign `x` in match guard
         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
-        //~^ ERROR cannot mutably borrow in a pattern guard
-        //~| ERROR cannot assign in a pattern guard
-        //~| ERROR cannot mutably borrow `x` in match guard
+        //~^ ERROR cannot mutably borrow `x` in match guard
         Enum::A(p) => *p,
         Enum::B(_) => 2,
     }
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
index 674f137..6d05e97 100644
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
@@ -1,23 +1,3 @@
-error[E0302]: cannot assign in a pattern guard
-  --> $DIR/borrowck-mutate-in-guard.rs:10:25
-   |
-LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
-   |                         ^^^^^^^^^^^^^^^^^^ assignment in pattern guard
-
-error[E0301]: cannot mutably borrow in a pattern guard
-  --> $DIR/borrowck-mutate-in-guard.rs:13:38
-   |
-LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
-   |                                      ^ borrowed mutably in pattern guard
-   |
-   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
-
-error[E0302]: cannot assign in a pattern guard
-  --> $DIR/borrowck-mutate-in-guard.rs:13:41
-   |
-LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
-   |                                         ^^^^^^^^^^^^^^^^^^^ assignment in pattern guard
-
 error[E0510]: cannot assign `x` in match guard
   --> $DIR/borrowck-mutate-in-guard.rs:10:25
    |
@@ -27,7 +7,7 @@
    |                         ^^^^^^^^^^^^^^^^^^ cannot assign
 
 error[E0510]: cannot mutably borrow `x` in match guard
-  --> $DIR/borrowck-mutate-in-guard.rs:13:33
+  --> $DIR/borrowck-mutate-in-guard.rs:12:33
    |
 LL |     match x {
    |           - value is immutable in match guard
@@ -35,7 +15,6 @@
 LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    |                                 ^^^^^^ cannot mutably borrow
 
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0301, E0302, E0510.
-For more information about an error, try `rustc --explain E0301`.
+For more information about this error, try `rustc --explain E0510`.
diff --git a/src/test/ui/borrowck/borrowck-or-init.rs b/src/test/ui/borrowck/borrowck-or-init.rs
index c0d6c9c..81b0b80 100644
--- a/src/test/ui/borrowck/borrowck-or-init.rs
+++ b/src/test/ui/borrowck/borrowck-or-init.rs
@@ -2,5 +2,5 @@
     let i: isize;
 
     println!("{}", false || { i = 5; true });
-    println!("{}", i); //~ ERROR borrow of possibly uninitialized variable: `i`
+    println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i`
 }
diff --git a/src/test/ui/borrowck/borrowck-or-init.stderr b/src/test/ui/borrowck/borrowck-or-init.stderr
index 122f519..3fe8d9e 100644
--- a/src/test/ui/borrowck/borrowck-or-init.stderr
+++ b/src/test/ui/borrowck/borrowck-or-init.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `i`
+error[E0381]: borrow of possibly-uninitialized variable: `i`
   --> $DIR/borrowck-or-init.rs:5:20
    |
 LL |     println!("{}", i);
-   |                    ^ use of possibly uninitialized `i`
+   |                    ^ use of possibly-uninitialized `i`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs
index 0fb955d..5e5a8cd 100644
--- a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs
@@ -15,7 +15,7 @@
 fn stuff() {
     let mut x : (Test2, Test2);
     (x.0).0 = Some(Test);
-    //~^ ERROR assign of possibly uninitialized variable: `x.0`
+    //~^ ERROR assign of possibly-uninitialized variable: `x.0`
 }
 
 fn main() {
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
index f0a9a7d..218c4f2 100644
--- a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
@@ -1,8 +1,8 @@
-error[E0381]: assign of possibly uninitialized variable: `x.0`
+error[E0381]: assign of possibly-uninitialized variable: `x.0`
   --> $DIR/borrowck-partial-reinit-4.rs:17:5
    |
 LL |     (x.0).0 = Some(Test);
-   |     ^^^^^^^ use of possibly uninitialized `x.0`
+   |     ^^^^^^^ use of possibly-uninitialized `x.0`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-return.rs b/src/test/ui/borrowck/borrowck-return.rs
index e5bee2c..8c62335 100644
--- a/src/test/ui/borrowck/borrowck-return.rs
+++ b/src/test/ui/borrowck/borrowck-return.rs
@@ -1,6 +1,6 @@
 fn f() -> isize {
     let x: isize;
-    return x; //~ ERROR use of possibly uninitialized variable: `x`
+    return x; //~ ERROR use of possibly-uninitialized variable: `x`
 }
 
 fn main() { f(); }
diff --git a/src/test/ui/borrowck/borrowck-return.stderr b/src/test/ui/borrowck/borrowck-return.stderr
index a2b65af..bc74e8e 100644
--- a/src/test/ui/borrowck/borrowck-return.stderr
+++ b/src/test/ui/borrowck/borrowck-return.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-return.rs:3:12
    |
 LL |     return x;
-   |            ^ use of possibly uninitialized `x`
+   |            ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-storage-dead.stderr b/src/test/ui/borrowck/borrowck-storage-dead.stderr
index 5b9f49c..8e49321 100644
--- a/src/test/ui/borrowck/borrowck-storage-dead.stderr
+++ b/src/test/ui/borrowck/borrowck-storage-dead.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-storage-dead.rs:16:17
    |
 LL |         let _ = x + 1;
-   |                 ^ use of possibly uninitialized `x`
+   |                 ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.rs b/src/test/ui/borrowck/borrowck-uninit-after-item.rs
index 83f3752..e9a3896 100644
--- a/src/test/ui/borrowck/borrowck-uninit-after-item.rs
+++ b/src/test/ui/borrowck/borrowck-uninit-after-item.rs
@@ -1,5 +1,5 @@
 fn main() {
     let bar;
     fn baz(_x: isize) { }
-    baz(bar); //~ ERROR use of possibly uninitialized variable: `bar`
+    baz(bar); //~ ERROR use of possibly-uninitialized variable: `bar`
 }
diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
index 2d0b21d..f7f069b 100644
--- a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `bar`
+error[E0381]: use of possibly-uninitialized variable: `bar`
   --> $DIR/borrowck-uninit-after-item.rs:4:9
    |
 LL |     baz(bar);
-   |         ^^^ use of possibly uninitialized `bar`
+   |         ^^^ use of possibly-uninitialized `bar`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
index aa214f9..9f35a4a 100644
--- a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `a`
+error[E0381]: use of possibly-uninitialized variable: `a`
   --> $DIR/borrowck-uninit-field-access.rs:21:13
    |
 LL |     let _ = a.x + 1;
-   |             ^^^ use of possibly uninitialized `a.x`
+   |             ^^^ use of possibly-uninitialized `a.x`
 
 error[E0382]: use of moved value: `line1.origin`
   --> $DIR/borrowck-uninit-field-access.rs:25:13
diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs
index bfb0dd4..20350d6 100644
--- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs
+++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs
@@ -3,32 +3,32 @@
 
 pub fn main() {
     let x: isize;
-    x += 1; //~ ERROR use of possibly uninitialized variable: `x`
+    x += 1; //~ ERROR use of possibly-uninitialized variable: `x`
 
     let x: isize;
-    x -= 1; //~ ERROR use of possibly uninitialized variable: `x`
+    x -= 1; //~ ERROR use of possibly-uninitialized variable: `x`
 
     let x: isize;
-    x *= 1; //~ ERROR use of possibly uninitialized variable: `x`
+    x *= 1; //~ ERROR use of possibly-uninitialized variable: `x`
 
     let x: isize;
-    x /= 1; //~ ERROR use of possibly uninitialized variable: `x`
+    x /= 1; //~ ERROR use of possibly-uninitialized variable: `x`
 
     let x: isize;
-    x %= 1; //~ ERROR use of possibly uninitialized variable: `x`
+    x %= 1; //~ ERROR use of possibly-uninitialized variable: `x`
 
     let x: isize;
-    x ^= 1; //~ ERROR use of possibly uninitialized variable: `x`
+    x ^= 1; //~ ERROR use of possibly-uninitialized variable: `x`
 
     let x: isize;
-    x &= 1; //~ ERROR use of possibly uninitialized variable: `x`
+    x &= 1; //~ ERROR use of possibly-uninitialized variable: `x`
 
     let x: isize;
-    x |= 1; //~ ERROR use of possibly uninitialized variable: `x`
+    x |= 1; //~ ERROR use of possibly-uninitialized variable: `x`
 
     let x: isize;
-    x <<= 1;    //~ ERROR use of possibly uninitialized variable: `x`
+    x <<= 1;    //~ ERROR use of possibly-uninitialized variable: `x`
 
     let x: isize;
-    x >>= 1;    //~ ERROR use of possibly uninitialized variable: `x`
+    x >>= 1;    //~ ERROR use of possibly-uninitialized variable: `x`
 }
diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
index 163395e..f2036df 100644
--- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
@@ -1,62 +1,62 @@
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:6:5
    |
 LL |     x += 1;
-   |     ^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:9:5
    |
 LL |     x -= 1;
-   |     ^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:12:5
    |
 LL |     x *= 1;
-   |     ^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:15:5
    |
 LL |     x /= 1;
-   |     ^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:18:5
    |
 LL |     x %= 1;
-   |     ^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:21:5
    |
 LL |     x ^= 1;
-   |     ^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:24:5
    |
 LL |     x &= 1;
-   |     ^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:27:5
    |
 LL |     x |= 1;
-   |     ^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:30:5
    |
 LL |     x <<= 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-in-assignop.rs:33:5
    |
 LL |     x >>= 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs
index fa9148f..0ccea49 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs
@@ -15,19 +15,19 @@
 
 
     let mut a: S<i32, i32>;
-    a.x = 0;            //~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+    a.x = 0;            //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381]
     let _b = &a.x;
 
     let mut a: S<&&i32, &&i32>;
-    a.x = &&0;          //~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+    a.x = &&0;          //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381]
     let _b = &**a.x;
 
 
     let mut a: S<i32, i32>;
-    a.x = 0;            //~ ERROR assign to part of possibly uninitialized variable: `a` [E0381]
+    a.x = 0;            //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381]
     let _b = &a.y;
 
     let mut a: S<&&i32, &&i32>;
-    a.x = &&0;          //~ assign to part of possibly uninitialized variable: `a` [E0381]
+    a.x = &&0;          //~ assign to part of possibly-uninitialized variable: `a` [E0381]
     let _b = &**a.y;
 }
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
index d87621f..d99a50d 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
@@ -1,44 +1,44 @@
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-ref-chain.rs:8:14
    |
 LL |     let _y = &**x;
-   |              ^^^^ use of possibly uninitialized `**x`
+   |              ^^^^ use of possibly-uninitialized `**x`
 
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-ref-chain.rs:11:14
    |
 LL |     let _y = &**x;
-   |              ^^^^ use of possibly uninitialized `**x`
+   |              ^^^^ use of possibly-uninitialized `**x`
 
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit-ref-chain.rs:14:14
    |
 LL |     let _y = &**x;
-   |              ^^^^ use of possibly uninitialized `**x`
+   |              ^^^^ use of possibly-uninitialized `**x`
 
-error[E0381]: assign to part of possibly uninitialized variable: `a`
+error[E0381]: assign to part of possibly-uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:18:5
    |
 LL |     a.x = 0;
-   |     ^^^^^^^ use of possibly uninitialized `a`
+   |     ^^^^^^^ use of possibly-uninitialized `a`
 
-error[E0381]: assign to part of possibly uninitialized variable: `a`
+error[E0381]: assign to part of possibly-uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:22:5
    |
 LL |     a.x = &&0;
-   |     ^^^^^^^^^ use of possibly uninitialized `a`
+   |     ^^^^^^^^^ use of possibly-uninitialized `a`
 
-error[E0381]: assign to part of possibly uninitialized variable: `a`
+error[E0381]: assign to part of possibly-uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:27:5
    |
 LL |     a.x = 0;
-   |     ^^^^^^^ use of possibly uninitialized `a`
+   |     ^^^^^^^ use of possibly-uninitialized `a`
 
-error[E0381]: assign to part of possibly uninitialized variable: `a`
+error[E0381]: assign to part of possibly-uninitialized variable: `a`
   --> $DIR/borrowck-uninit-ref-chain.rs:31:5
    |
 LL |     a.x = &&0;
-   |     ^^^^^^^^^ use of possibly uninitialized `a`
+   |     ^^^^^^^^^ use of possibly-uninitialized `a`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-uninit.rs b/src/test/ui/borrowck/borrowck-uninit.rs
index 71c1f59..017b955 100644
--- a/src/test/ui/borrowck/borrowck-uninit.rs
+++ b/src/test/ui/borrowck/borrowck-uninit.rs
@@ -2,5 +2,5 @@
 
 fn main() {
     let x: isize;
-    foo(x); //~ ERROR use of possibly uninitialized variable: `x`
+    foo(x); //~ ERROR use of possibly-uninitialized variable: `x`
 }
diff --git a/src/test/ui/borrowck/borrowck-uninit.stderr b/src/test/ui/borrowck/borrowck-uninit.stderr
index 5db9c1b..effc209 100644
--- a/src/test/ui/borrowck/borrowck-uninit.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-uninit.rs:5:9
    |
 LL |     foo(x);
-   |         ^ use of possibly uninitialized `x`
+   |         ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.rs b/src/test/ui/borrowck/borrowck-union-uninitialized.rs
index 9cab0b1..3cc71e7 100644
--- a/src/test/ui/borrowck/borrowck-union-uninitialized.rs
+++ b/src/test/ui/borrowck/borrowck-union-uninitialized.rs
@@ -10,8 +10,8 @@
     unsafe {
         let mut s: S;
         let mut u: U;
-        s.a = 0; //~ ERROR assign to part of possibly uninitialized variable: `s`
-        u.a = 0; //~ ERROR assign to part of possibly uninitialized variable: `u`
+        s.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `s`
+        u.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `u`
         let sa = s.a;
         let ua = u.a;
     }
diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
index 06c884e..bd9ec5e 100644
--- a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
+++ b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
@@ -1,14 +1,14 @@
-error[E0381]: assign to part of possibly uninitialized variable: `s`
+error[E0381]: assign to part of possibly-uninitialized variable: `s`
   --> $DIR/borrowck-union-uninitialized.rs:13:9
    |
 LL |         s.a = 0;
-   |         ^^^^^^^ use of possibly uninitialized `s`
+   |         ^^^^^^^ use of possibly-uninitialized `s`
 
-error[E0381]: assign to part of possibly uninitialized variable: `u`
+error[E0381]: assign to part of possibly-uninitialized variable: `u`
   --> $DIR/borrowck-union-uninitialized.rs:14:9
    |
 LL |         u.a = 0;
-   |         ^^^^^^^ use of possibly uninitialized `u`
+   |         ^^^^^^^ use of possibly-uninitialized `u`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
index c03ef75..d1b396a 100644
--- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
@@ -1,14 +1,14 @@
-error[E0381]: use of possibly uninitialized variable: `w`
+error[E0381]: use of possibly-uninitialized variable: `w`
   --> $DIR/borrowck-use-in-index-lvalue.rs:3:5
    |
 LL |     w[5] = 0;
-   |     ^^^^ use of possibly uninitialized `*w`
+   |     ^^^^ use of possibly-uninitialized `*w`
 
-error[E0381]: use of possibly uninitialized variable: `w`
+error[E0381]: use of possibly-uninitialized variable: `w`
   --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
    |
 LL |     w[5] = 0;
-   |     ^^^^ use of possibly uninitialized `*w`
+   |     ^^^^ use of possibly-uninitialized `*w`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
index 2b80140..ca5227c 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13
    |
 LL |     let y = x as *const dyn Foo;
-   |             ^ use of possibly uninitialized `*x`
+   |             ^ use of possibly-uninitialized `*x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
index 84e717a..24897a0 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-use-uninitialized-in-cast.rs:7:13
    |
 LL |     let y = x as *const i32;
-   |             ^ use of possibly uninitialized `*x`
+   |             ^ use of possibly-uninitialized `*x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-while-break.rs b/src/test/ui/borrowck/borrowck-while-break.rs
index e16bc58..48e4221 100644
--- a/src/test/ui/borrowck/borrowck-while-break.rs
+++ b/src/test/ui/borrowck/borrowck-while-break.rs
@@ -4,7 +4,7 @@
         v = 3;
         break;
     }
-    println!("{}", v); //~ ERROR borrow of possibly uninitialized variable: `v`
+    println!("{}", v); //~ ERROR borrow of possibly-uninitialized variable: `v`
 }
 
 fn main() {
diff --git a/src/test/ui/borrowck/borrowck-while-break.stderr b/src/test/ui/borrowck/borrowck-while-break.stderr
index 0fe3cdc..3eaaf8d 100644
--- a/src/test/ui/borrowck/borrowck-while-break.stderr
+++ b/src/test/ui/borrowck/borrowck-while-break.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `v`
+error[E0381]: borrow of possibly-uninitialized variable: `v`
   --> $DIR/borrowck-while-break.rs:7:20
    |
 LL |     println!("{}", v);
-   |                    ^ use of possibly uninitialized `v`
+   |                    ^ use of possibly-uninitialized `v`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-while-cond.rs b/src/test/ui/borrowck/borrowck-while-cond.rs
index 28a5fb1..b3ec207 100644
--- a/src/test/ui/borrowck/borrowck-while-cond.rs
+++ b/src/test/ui/borrowck/borrowck-while-cond.rs
@@ -1,4 +1,4 @@
 fn main() {
     let x: bool;
-    while x { } //~ ERROR use of possibly uninitialized variable: `x`
+    while x { } //~ ERROR use of possibly-uninitialized variable: `x`
 }
diff --git a/src/test/ui/borrowck/borrowck-while-cond.stderr b/src/test/ui/borrowck/borrowck-while-cond.stderr
index 06deae3..92937a9 100644
--- a/src/test/ui/borrowck/borrowck-while-cond.stderr
+++ b/src/test/ui/borrowck/borrowck-while-cond.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-while-cond.rs:3:11
    |
 LL |     while x { }
-   |           ^ use of possibly uninitialized `x`
+   |           ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-while.rs b/src/test/ui/borrowck/borrowck-while.rs
index 4274fa9..6b3220c 100644
--- a/src/test/ui/borrowck/borrowck-while.rs
+++ b/src/test/ui/borrowck/borrowck-while.rs
@@ -1,7 +1,7 @@
 fn f() -> isize {
     let mut x: isize;
     while 1 == 1 { x = 10; }
-    return x; //~ ERROR use of possibly uninitialized variable: `x`
+    return x; //~ ERROR use of possibly-uninitialized variable: `x`
 }
 
 fn main() { f(); }
diff --git a/src/test/ui/borrowck/borrowck-while.stderr b/src/test/ui/borrowck/borrowck-while.stderr
index 60622d6..a1f8f64 100644
--- a/src/test/ui/borrowck/borrowck-while.stderr
+++ b/src/test/ui/borrowck/borrowck-while.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/borrowck-while.rs:4:12
    |
 LL |     return x;
-   |            ^ use of possibly uninitialized `x`
+   |            ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs
index a987c00..7043cb3 100644
--- a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs
+++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs
@@ -4,19 +4,19 @@
 fn main() {
     let mut t: (u64, u64);
     t.0 = 1;
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
     t.1 = 1;
 
     let mut t: (u64, u64);
     t.1 = 1;
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
     t.0 = 1;
 
     let mut t: (u64, u64);
     t.0 = 1;
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
 
     let mut t: (u64,);
     t.0 = 1;
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
 }
diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr
index a32b17b..8d5b393 100644
--- a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr
+++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr
@@ -1,26 +1,26 @@
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/disallow-possibly-uninitialized.rs:6:5
    |
 LL |     t.0 = 1;
-   |     ^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/disallow-possibly-uninitialized.rs:11:5
    |
 LL |     t.1 = 1;
-   |     ^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/disallow-possibly-uninitialized.rs:16:5
    |
 LL |     t.0 = 1;
-   |     ^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/disallow-possibly-uninitialized.rs:20:5
    |
 LL |     t.0 = 1;
-   |     ^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^ use of possibly-uninitialized `t`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/borrowck/issue-10876.rs b/src/test/ui/borrowck/issue-10876.rs
index 20ab905..22eaa11 100644
--- a/src/test/ui/borrowck/issue-10876.rs
+++ b/src/test/ui/borrowck/issue-10876.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 enum Nat {
     S(Box<Nat>),
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs
index 8d8ac27..f031a14 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs
@@ -10,7 +10,7 @@
     {
         let mut t: Tuple;
         t.0 = S(1);
-        //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
         t.1 = 2;
         println!("{:?} {:?}", t.0, t.1);
     }
@@ -18,7 +18,7 @@
     {
         let mut u: Tpair;
         u.0 = S(1);
-        //~^ ERROR assign to part of possibly uninitialized variable: `u` [E0381]
+        //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381]
         u.1 = 2;
         println!("{:?} {:?}", u.0, u.1);
     }
@@ -26,7 +26,7 @@
     {
         let mut v: Spair;
         v.x = S(1);
-        //~^ ERROR assign to part of possibly uninitialized variable: `v` [E0381]
+        //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381]
         v.y = 2;
         println!("{:?} {:?}", v.x, v.y);
     }
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr
index 6f18ff1..22c6c39 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr
@@ -1,20 +1,20 @@
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:12:9
    |
 LL |         t.0 = S(1);
-   |         ^^^^^^^^^^ use of possibly uninitialized `t`
+   |         ^^^^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `u`
+error[E0381]: assign to part of possibly-uninitialized variable: `u`
   --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:20:9
    |
 LL |         u.0 = S(1);
-   |         ^^^^^^^^^^ use of possibly uninitialized `u`
+   |         ^^^^^^^^^^ use of possibly-uninitialized `u`
 
-error[E0381]: assign to part of possibly uninitialized variable: `v`
+error[E0381]: assign to part of possibly-uninitialized variable: `v`
   --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:28:9
    |
 LL |         v.x = S(1);
-   |         ^^^^^^^^^^ use of possibly uninitialized `v`
+   |         ^^^^^^^^^^ use of possibly-uninitialized `v`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs
index 1a1b376..660d9e8 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs
@@ -10,7 +10,7 @@
     {
         let t: Tuple;
         t.0 = S(1);
-        //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
         t.1 = 2;
         println!("{:?} {:?}", t.0, t.1);
     }
@@ -18,7 +18,7 @@
     {
         let u: Tpair;
         u.0 = S(1);
-        //~^ ERROR assign to part of possibly uninitialized variable: `u` [E0381]
+        //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381]
         u.1 = 2;
         println!("{:?} {:?}", u.0, u.1);
     }
@@ -26,7 +26,7 @@
     {
         let v: Spair;
         v.x = S(1);
-        //~^ ERROR assign to part of possibly uninitialized variable: `v` [E0381]
+        //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381]
         v.y = 2;
         println!("{:?} {:?}", v.x, v.y);
     }
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr
index 68873ac..5f9c978 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr
@@ -1,20 +1,20 @@
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/issue-54499-field-mutation-of-never-init.rs:12:9
    |
 LL |         t.0 = S(1);
-   |         ^^^^^^^^^^ use of possibly uninitialized `t`
+   |         ^^^^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `u`
+error[E0381]: assign to part of possibly-uninitialized variable: `u`
   --> $DIR/issue-54499-field-mutation-of-never-init.rs:20:9
    |
 LL |         u.0 = S(1);
-   |         ^^^^^^^^^^ use of possibly uninitialized `u`
+   |         ^^^^^^^^^^ use of possibly-uninitialized `u`
 
-error[E0381]: assign to part of possibly uninitialized variable: `v`
+error[E0381]: assign to part of possibly-uninitialized variable: `v`
   --> $DIR/issue-54499-field-mutation-of-never-init.rs:28:9
    |
 LL |         v.x = S(1);
-   |         ^^^^^^^^^^ use of possibly uninitialized `v`
+   |         ^^^^^^^^^^ use of possibly-uninitialized `v`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs
index 220b2ec..f8efa8c 100644
--- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs
+++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs
@@ -1,7 +1,7 @@
 fn main() {
     let e: i32;
     match e {
-        //~^ ERROR use of possibly uninitialized variable
+        //~^ ERROR use of possibly-uninitialized variable
         ref u if true => {}
         ref v if true => {
             let tx = 0;
diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
index 9701343..0eca447 100644
--- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
+++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `e`
+error[E0381]: use of possibly-uninitialized variable: `e`
   --> $DIR/issue-62107-match-arm-scopes.rs:3:11
    |
 LL |     match e {
-   |           ^ use of possibly uninitialized `e`
+   |           ^ use of possibly-uninitialized `e`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.stderr
index d455a8f..f09db37 100644
--- a/src/test/ui/borrowck/reassignment_immutable_fields.stderr
+++ b/src/test/ui/borrowck/reassignment_immutable_fields.stderr
@@ -1,14 +1,14 @@
-error[E0381]: assign to part of possibly uninitialized variable: `x`
+error[E0381]: assign to part of possibly-uninitialized variable: `x`
   --> $DIR/reassignment_immutable_fields.rs:7:5
    |
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
-error[E0381]: assign to part of possibly uninitialized variable: `x`
+error[E0381]: assign to part of possibly-uninitialized variable: `x`
   --> $DIR/reassignment_immutable_fields.rs:15:5
    |
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
index 649c127..5f34670 100644
--- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
@@ -1,8 +1,8 @@
-error[E0381]: assign to part of possibly uninitialized variable: `x`
+error[E0381]: assign to part of possibly-uninitialized variable: `x`
   --> $DIR/reassignment_immutable_fields_overlapping.rs:12:5
    |
 LL |     x.a = 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
 error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable
   --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
index 9a2824c..14f0fee 100644
--- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
@@ -7,11 +7,11 @@
 LL |     x.0 = 1;
    |     ^^^^^^^ cannot assign
 
-error[E0381]: assign to part of possibly uninitialized variable: `x`
+error[E0381]: assign to part of possibly-uninitialized variable: `x`
   --> $DIR/reassignment_immutable_fields_twice.rs:12:5
    |
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly uninitialized `x`
+   |     ^^^^^^^ use of possibly-uninitialized `x`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/two-phase-across-loop.rs b/src/test/ui/borrowck/two-phase-across-loop.rs
index 1222234..3fcea7d 100644
--- a/src/test/ui/borrowck/two-phase-across-loop.rs
+++ b/src/test/ui/borrowck/two-phase-across-loop.rs
@@ -1,4 +1,4 @@
-// Test that a borrow which starts as a 2-phase borrow and gets
+// Test that a borrow which starts as a two-phase borrow and gets
 // carried around a loop winds up conflicting with itself.
 
 struct Foo { x: String }
diff --git a/src/test/ui/borrowck/two-phase-multiple-activations.rs b/src/test/ui/borrowck/two-phase-multiple-activations.rs
index a7fa7fa..599138a 100644
--- a/src/test/ui/borrowck/two-phase-multiple-activations.rs
+++ b/src/test/ui/borrowck/two-phase-multiple-activations.rs
@@ -11,7 +11,7 @@
 }
 
 impl FakeRead for Foo {
-    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
+    fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> Result<usize> {
         Ok(4)
     }
 }
@@ -19,5 +19,5 @@
 fn main() {
     let mut a = Foo {};
     let mut v = Vec::new();
-    a.read_to_end(&mut v);
+    a.read_to_end(&mut v).unwrap();
 }
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
index 4947d6e..ab8398e 100644
--- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
@@ -37,11 +37,11 @@
   --> $DIR/variadic-ffi-4.rs:20:5
    |
 LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
-   |                                               -------                   ------- has type `core::ffi::VaListImpl<'1>`
+   |                                               -------                   ------- has type `core::ffi::VaListImpl<'2>`
    |                                               |
-   |                                               has type `&mut core::ffi::VaListImpl<'2>`
+   |                                               has type `&mut core::ffi::VaListImpl<'1>`
 LL |     *ap0 = ap1;
-   |     ^^^^ assignment requires that `'1` must outlive `'2`
+   |     ^^^^ assignment requires that `'2` must outlive `'1`
 
 error: lifetime may not live long enough
   --> $DIR/variadic-ffi-4.rs:25:5
@@ -57,11 +57,11 @@
   --> $DIR/variadic-ffi-4.rs:25:5
    |
 LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
-   |                                               ---                   ------- has type `core::ffi::VaListImpl<'1>`
+   |                                               ---                   ------- has type `core::ffi::VaListImpl<'2>`
    |                                               |
-   |                                               has type `&mut core::ffi::VaListImpl<'2>`
+   |                                               has type `&mut core::ffi::VaListImpl<'1>`
 LL |     ap0 = &mut ap1;
-   |     ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+   |     ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1`
 
 error[E0384]: cannot assign to immutable argument `ap0`
   --> $DIR/variadic-ffi-4.rs:25:5
@@ -99,11 +99,11 @@
   --> $DIR/variadic-ffi-4.rs:33:12
    |
 LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
-   |                                               -------                   ------- has type `core::ffi::VaListImpl<'1>`
+   |                                               -------                   ------- has type `core::ffi::VaListImpl<'2>`
    |                                               |
-   |                                               has type `&mut core::ffi::VaListImpl<'2>`
+   |                                               has type `&mut core::ffi::VaListImpl<'1>`
 LL |     *ap0 = ap1.clone();
-   |            ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |            ^^^^^^^^^^^ argument requires that `'2` must outlive `'1`
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr
index 6cb33f2..15c52f4 100644
--- a/src/test/ui/chalkify/type_inference.stderr
+++ b/src/test/ui/chalkify/type_inference.stderr
@@ -10,17 +10,15 @@
 error[E0277]: the trait bound `{float}: Bar` is not satisfied
   --> $DIR/type_inference.rs:25:5
    |
+LL | fn only_bar<T: Bar>(_x: T) { }
+   | -------------------------- required by `only_bar`
+...
 LL |     only_bar(x);
    |     ^^^^^^^^ the trait `Bar` is not implemented for `{float}`
    |
    = help: the following implementations were found:
              <i32 as Bar>
              <u32 as Bar>
-note: required by `only_bar`
-  --> $DIR/type_inference.rs:12:1
-   |
-LL | fn only_bar<T: Bar>(_x: T) { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/class-cast-to-trait.stderr b/src/test/ui/class-cast-to-trait.stderr
index 39f308c..4cab52e 100644
--- a/src/test/ui/class-cast-to-trait.stderr
+++ b/src/test/ui/class-cast-to-trait.stderr
@@ -2,7 +2,7 @@
   --> $DIR/class-cast-to-trait.rs:53:8
    |
 LL |   nyan.eat();
-   |        ^^^
+   |        ^^^ method not found in `std::boxed::Box<dyn Noisy>`
 
 error: aborting due to previous error
 
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 7e4ac4e..565c60e 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
@@ -1,53 +1,44 @@
 error[E0631]: type mismatch in closure arguments
   --> $DIR/expect-fn-supply-fn.rs:30:5
    |
-LL |     with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
-   |     |
-   |     expected signature of `fn(fn(&'a u32), &i32) -> _`
-   |
-note: required by `with_closure_expecting_fn_with_free_region`
-  --> $DIR/expect-fn-supply-fn.rs:1:1
-   |
 LL | / fn with_closure_expecting_fn_with_free_region<F>(_: F)
 LL | |     where F: for<'a> FnOnce(fn(&'a u32), &i32)
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `with_closure_expecting_fn_with_free_region`
+...
+LL |       with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
+   |       |
+   |       expected signature of `fn(fn(&'a u32), &i32) -> _`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/expect-fn-supply-fn.rs:37:5
    |
-LL |     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
-   |     |
-   |     expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
-   |
-note: required by `with_closure_expecting_fn_with_bound_region`
-  --> $DIR/expect-fn-supply-fn.rs:6:1
-   |
 LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F)
 LL | |     where F: FnOnce(fn(&u32), &i32)
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `with_closure_expecting_fn_with_bound_region`
+...
+LL |       with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
+   |       |
+   |       expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/expect-fn-supply-fn.rs:46:5
    |
-LL |     with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _`
-   |     |
-   |     expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
-   |
-note: required by `with_closure_expecting_fn_with_bound_region`
-  --> $DIR/expect-fn-supply-fn.rs:6:1
-   |
 LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F)
 LL | |     where F: FnOnce(fn(&u32), &i32)
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `with_closure_expecting_fn_with_bound_region`
+...
+LL |       with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _`
+   |       |
+   |       expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
 
 error: aborting due to 3 previous errors
 
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 40fab4d..c618c2c 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
@@ -39,53 +39,44 @@
 error[E0631]: type mismatch in closure arguments
   --> $DIR/expect-fn-supply-fn.rs:30:5
    |
-LL |     with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
-   |     |
-   |     expected signature of `fn(fn(&'a u32), &i32) -> _`
-   |
-note: required by `with_closure_expecting_fn_with_free_region`
-  --> $DIR/expect-fn-supply-fn.rs:1:1
-   |
 LL | / fn with_closure_expecting_fn_with_free_region<F>(_: F)
 LL | |     where F: for<'a> FnOnce(fn(&'a u32), &i32)
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `with_closure_expecting_fn_with_free_region`
+...
+LL |       with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
+   |       |
+   |       expected signature of `fn(fn(&'a u32), &i32) -> _`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/expect-fn-supply-fn.rs:37:5
    |
-LL |     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
-   |     |
-   |     expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
-   |
-note: required by `with_closure_expecting_fn_with_bound_region`
-  --> $DIR/expect-fn-supply-fn.rs:6:1
-   |
 LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F)
 LL | |     where F: FnOnce(fn(&u32), &i32)
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `with_closure_expecting_fn_with_bound_region`
+...
+LL |       with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
+   |       |
+   |       expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/expect-fn-supply-fn.rs:46:5
    |
-LL |     with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _`
-   |     |
-   |     expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
-   |
-note: required by `with_closure_expecting_fn_with_bound_region`
-  --> $DIR/expect-fn-supply-fn.rs:6:1
-   |
 LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F)
 LL | |     where F: FnOnce(fn(&u32), &i32)
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `with_closure_expecting_fn_with_bound_region`
+...
+LL |       with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _`
+   |       |
+   |       expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
 
 error: aborting due to 5 previous errors
 
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 c9a6974..a2b3a66 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
@@ -1,19 +1,16 @@
 error[E0631]: type mismatch in closure arguments
   --> $DIR/expect-infer-var-appearing-twice.rs:14:5
    |
-LL |     with_closure(|x: u32, y: i32| {
-   |     ^^^^^^^^^^^^ ---------------- found signature of `fn(u32, i32) -> _`
-   |     |
-   |     expected signature of `fn(_, _) -> _`
-   |
-note: required by `with_closure`
-  --> $DIR/expect-infer-var-appearing-twice.rs:1:1
-   |
 LL | / fn with_closure<F, A>(_: F)
 LL | |     where F: FnOnce(A, A)
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `with_closure`
+...
+LL |       with_closure(|x: u32, y: i32| {
+   |       ^^^^^^^^^^^^ ---------------- found signature of `fn(u32, i32) -> _`
+   |       |
+   |       expected signature of `fn(_, _) -> _`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr
index 81c4f4e..51077b1 100644
--- a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr
+++ b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr
@@ -1,6 +1,9 @@
 error[E0277]: `F` cannot be sent between threads safely
   --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:5:1
    |
+LL |   struct X<F> where F: FnOnce() + 'static + Send {
+   |   ---------------------------------------------- required by `X`
+...
 LL | / fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static {
 LL | |
 LL | |     return X { field: blk };
@@ -9,11 +12,6 @@
    |
    = help: the trait `std::marker::Send` is not implemented for `F`
    = help: consider adding a `where F: std::marker::Send` bound
-note: required by `X`
-  --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:1:1
-   |
-LL | struct X<F> where F: FnOnce() + 'static + Send {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr
index 3b9fd10..4958bd0 100644
--- a/src/test/ui/closures/closure-bounds-subtype.stderr
+++ b/src/test/ui/closures/closure-bounds-subtype.stderr
@@ -1,16 +1,14 @@
 error[E0277]: `F` cannot be shared between threads safely
   --> $DIR/closure-bounds-subtype.rs:13:5
    |
+LL | fn take_const_owned<F>(_: F) where F: FnOnce() + Sync + Send {
+   | ------------------------------------------------------------ required by `take_const_owned`
+...
 LL |     take_const_owned(f);
    |     ^^^^^^^^^^^^^^^^ `F` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `F`
    = help: consider adding a `where F: std::marker::Sync` bound
-note: required by `take_const_owned`
-  --> $DIR/closure-bounds-subtype.rs:4:1
-   |
-LL | fn take_const_owned<F>(_: F) where F: FnOnce() + Sync + Send {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/bad-format-args.rs b/src/test/ui/codemap_tests/bad-format-args.rs
index 9f90185..dff2483 100644
--- a/src/test/ui/codemap_tests/bad-format-args.rs
+++ b/src/test/ui/codemap_tests/bad-format-args.rs
@@ -1,5 +1,5 @@
 fn main() {
     format!(); //~ ERROR requires at least a format string argument
     format!("" 1); //~ ERROR expected token: `,`
-    format!("", 1 1); //~ ERROR expected token: `,`
+    format!("", 1 1); //~ ERROR expected one of
 }
diff --git a/src/test/ui/codemap_tests/bad-format-args.stderr b/src/test/ui/codemap_tests/bad-format-args.stderr
index 5b01314..3372ef6 100644
--- a/src/test/ui/codemap_tests/bad-format-args.stderr
+++ b/src/test/ui/codemap_tests/bad-format-args.stderr
@@ -12,11 +12,11 @@
 LL |     format!("" 1);
    |                ^ expected `,`
 
-error: expected token: `,`
+error: expected one of `,`, `.`, `?`, or an operator, found `1`
   --> $DIR/bad-format-args.rs:4:19
    |
 LL |     format!("", 1 1);
-   |                   ^ expected `,`
+   |                   ^ expected one of `,`, `.`, `?`, or an operator here
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/coercion/coercion-slice.rs b/src/test/ui/coercion/coercion-slice.rs
index 312b634..b69edcf 100644
--- a/src/test/ui/coercion/coercion-slice.rs
+++ b/src/test/ui/coercion/coercion-slice.rs
@@ -4,5 +4,5 @@
     let _: &[i32] = [0];
     //~^ ERROR mismatched types
     //~| expected type `&[i32]`
-    //~| expected &[i32], found array of 1 elements
+    //~| expected &[i32], found array of 1 element
 }
diff --git a/src/test/ui/coercion/coercion-slice.stderr b/src/test/ui/coercion/coercion-slice.stderr
index 6fa7123..ccd776e 100644
--- a/src/test/ui/coercion/coercion-slice.stderr
+++ b/src/test/ui/coercion/coercion-slice.stderr
@@ -4,7 +4,7 @@
 LL |     let _: &[i32] = [0];
    |                     ^^^
    |                     |
-   |                     expected &[i32], found array of 1 elements
+   |                     expected &[i32], found array of 1 element
    |                     help: consider borrowing here: `&[0]`
    |
    = note: expected type `&[i32]`
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr
index c38d745..18a7cea 100644
--- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr
+++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr
@@ -1,10 +1,10 @@
 error[E0038]: the trait `NotObjectSafe` cannot be made into an object
   --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
    |
+LL | trait NotObjectSafe { fn eq(&self, other: Self); }
+   |                          -- method `eq` references the `Self` type in its parameters or return type
 LL | impl NotObjectSafe for dyn NotObjectSafe { }
    |      ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
-   |
-   = note: method `eq` references the `Self` type in its arguments or return type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr
index c38d745..18a7cea 100644
--- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr
+++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr
@@ -1,10 +1,10 @@
 error[E0038]: the trait `NotObjectSafe` cannot be made into an object
   --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
    |
+LL | trait NotObjectSafe { fn eq(&self, other: Self); }
+   |                          -- method `eq` references the `Self` type in its parameters or return type
 LL | impl NotObjectSafe for dyn NotObjectSafe { }
    |      ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
-   |
-   = note: method `eq` references the `Self` type in its arguments or return type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/coherence_inherent.old.stderr b/src/test/ui/coherence/coherence_inherent.old.stderr
index fa56445..750d243 100644
--- a/src/test/ui/coherence/coherence_inherent.old.stderr
+++ b/src/test/ui/coherence/coherence_inherent.old.stderr
@@ -2,7 +2,7 @@
   --> $DIR/coherence_inherent.rs:35:11
    |
 LL |         s.the_fn();
-   |           ^^^^^^
+   |           ^^^^^^ method not found in `&Lib::TheStruct`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/coherence/coherence_inherent.re.stderr b/src/test/ui/coherence/coherence_inherent.re.stderr
index fa56445..750d243 100644
--- a/src/test/ui/coherence/coherence_inherent.re.stderr
+++ b/src/test/ui/coherence/coherence_inherent.re.stderr
@@ -2,7 +2,7 @@
   --> $DIR/coherence_inherent.rs:35:11
    |
 LL |         s.the_fn();
-   |           ^^^^^^
+   |           ^^^^^^ method not found in `&Lib::TheStruct`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/coherence/coherence_inherent_cc.old.stderr b/src/test/ui/coherence/coherence_inherent_cc.old.stderr
index 4d93e69..59166a4 100644
--- a/src/test/ui/coherence/coherence_inherent_cc.old.stderr
+++ b/src/test/ui/coherence/coherence_inherent_cc.old.stderr
@@ -2,7 +2,7 @@
   --> $DIR/coherence_inherent_cc.rs:26:11
    |
 LL |         s.the_fn();
-   |           ^^^^^^
+   |           ^^^^^^ method not found in `&coherence_inherent_cc_lib::TheStruct`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/coherence/coherence_inherent_cc.re.stderr b/src/test/ui/coherence/coherence_inherent_cc.re.stderr
index 4d93e69..59166a4 100644
--- a/src/test/ui/coherence/coherence_inherent_cc.re.stderr
+++ b/src/test/ui/coherence/coherence_inherent_cc.re.stderr
@@ -2,7 +2,7 @@
   --> $DIR/coherence_inherent_cc.rs:26:11
    |
 LL |         s.the_fn();
-   |           ^^^^^^
+   |           ^^^^^^ method not found in `&coherence_inherent_cc_lib::TheStruct`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/coherence/conflicting-impl-with-err.rs b/src/test/ui/coherence/conflicting-impl-with-err.rs
new file mode 100644
index 0000000..3e0234b
--- /dev/null
+++ b/src/test/ui/coherence/conflicting-impl-with-err.rs
@@ -0,0 +1,16 @@
+struct ErrorKind;
+struct Error(ErrorKind);
+
+impl From<nope::Thing> for Error { //~ ERROR failed to resolve
+    fn from(_: nope::Thing) -> Self { //~ ERROR failed to resolve
+        unimplemented!()
+    }
+}
+
+impl From<ErrorKind> for Error {
+    fn from(_: ErrorKind) -> Self {
+        unimplemented!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/conflicting-impl-with-err.stderr b/src/test/ui/coherence/conflicting-impl-with-err.stderr
new file mode 100644
index 0000000..a8a5730
--- /dev/null
+++ b/src/test/ui/coherence/conflicting-impl-with-err.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: use of undeclared type or module `nope`
+  --> $DIR/conflicting-impl-with-err.rs:4:11
+   |
+LL | impl From<nope::Thing> for Error {
+   |           ^^^^ use of undeclared type or module `nope`
+
+error[E0433]: failed to resolve: use of undeclared type or module `nope`
+  --> $DIR/conflicting-impl-with-err.rs:5:16
+   |
+LL |     fn from(_: nope::Thing) -> Self {
+   |                ^^^^ use of undeclared type or module `nope`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/collections-const-new.rs b/src/test/ui/collections-const-new.rs
index e01b0df..a93f9a1 100644
--- a/src/test/ui/collections-const-new.rs
+++ b/src/test/ui/collections-const-new.rs
@@ -1,15 +1,11 @@
-// run-pass
+// check-pass
 
-#![allow(dead_code)]
 // Test several functions can be used for constants
 // 1. Vec::new()
 // 2. String::new()
 
-#![feature(const_vec_new)]
-#![feature(const_string_new)]
-
 const MY_VEC: Vec<usize> = Vec::new();
 
 const MY_STRING: String = String::new();
 
-pub fn main() {}
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs
new file mode 100644
index 0000000..9fa726f
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a{
+// error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr
new file mode 100644
index 0000000..7d2087b
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr
@@ -0,0 +1,2 @@
+error: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`)
+
diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr
index db3c7ac..e9df780 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr
@@ -1,6 +1,9 @@
 error[E0601]: `main` function not found in crate `cfg_attr_cfg_2`
+  --> $DIR/cfg-attr-cfg-2.rs:8:1
    |
-   = note: consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
+LL | / #[cfg_attr(foo, cfg(bar))]
+LL | | fn main() { }
+   | |_____________^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
index 22dbac7..45b757e 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
@@ -1,7 +1,7 @@
 macro_rules! foo {
     () => {
         #[cfg_attr(all(), unknown)]
-        //~^ ERROR cannot find attribute macro `unknown` in this scope
+        //~^ ERROR cannot find attribute `unknown` in this scope
         fn foo() {}
     }
 }
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
index c7c52a2..ef434ec 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:3:27
    |
 LL |         #[cfg_attr(all(), unknown)]
diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.rs b/src/test/ui/conditional-compilation/cfg-generic-params.rs
index d80d3ea..53aa355 100644
--- a/src/test/ui/conditional-compilation/cfg-generic-params.rs
+++ b/src/test/ui/conditional-compilation/cfg-generic-params.rs
@@ -16,21 +16,23 @@
 //~^ ERROR only lifetime parameters can be used in this context
 
 fn f_lt_no<#[cfg_attr(no, unknown)] 'a>() {} // OK
-fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} //~ ERROR attribute `unknown` is currently unknown
+fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
+//~^ ERROR cannot find attribute `unknown` in this scope
 fn f_ty_no<#[cfg_attr(no, unknown)] T>() {} // OK
-fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} //~ ERROR attribute `unknown` is currently unknown
+fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
+//~^ ERROR cannot find attribute `unknown` in this scope
 
 type FnNo = for<#[cfg_attr(no, unknown)] 'a> fn(); // OK
 type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
-//~^ ERROR attribute `unknown` is currently unknown
+//~^ ERROR cannot find attribute `unknown` in this scope
 
 type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK
 type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
-//~^ ERROR attribute `unknown` is currently unknown
+//~^ ERROR cannot find attribute `unknown` in this scope
 
 struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK
 struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
-//~^ ERROR attribute `unknown` is currently unknown
+//~^ ERROR cannot find attribute `unknown` in this scope
 
 fn main() {
     f_lt::<'static>();
diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.stderr b/src/test/ui/conditional-compilation/cfg-generic-params.stderr
index 1f9731f..d9e29c8 100644
--- a/src/test/ui/conditional-compilation/cfg-generic-params.stderr
+++ b/src/test/ui/conditional-compilation/cfg-generic-params.stderr
@@ -16,51 +16,35 @@
 LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
    |                                                      ^
 
-error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
+error: cannot find attribute `unknown` in this scope
+  --> $DIR/cfg-generic-params.rs:34:43
+   |
+LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
+   |                                           ^^^^^^^
+
+error: cannot find attribute `unknown` in this scope
+  --> $DIR/cfg-generic-params.rs:30:40
+   |
+LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
+   |                                        ^^^^^^^
+
+error: cannot find attribute `unknown` in this scope
+  --> $DIR/cfg-generic-params.rs:26:34
+   |
+LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
+   |                                  ^^^^^^^
+
+error: cannot find attribute `unknown` in this scope
+  --> $DIR/cfg-generic-params.rs:22:29
+   |
+LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
+   |                             ^^^^^^^
+
+error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-generic-params.rs:19:29
    |
 LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
    |                             ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/cfg-generic-params.rs:21:29
-   |
-LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
-   |                             ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/cfg-generic-params.rs:24:34
-   |
-LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
-   |                                  ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/cfg-generic-params.rs:28:40
-   |
-LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
-   |                                        ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/cfg-generic-params.rs:32:43
-   |
-LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
-   |                                           ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
 
 error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr
index c6d42c7..0b5c3e0 100644
--- a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr
+++ b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr
@@ -1,6 +1,8 @@
 error[E0601]: `main` function not found in crate `cfg_in_crate_1`
+  --> $DIR/cfg-in-crate-1.rs:3:1
    |
-   = note: consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
+LL | #![cfg(bar)]
+   | ^^^^^^^^^^^^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/apit-with-const-param.rs b/src/test/ui/const-generics/apit-with-const-param.rs
index 70e718d..7acc508 100644
--- a/src/test/ui/const-generics/apit-with-const-param.rs
+++ b/src/test/ui/const-generics/apit-with-const-param.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
diff --git a/src/test/ui/const-generics/array-wrapper-struct-ctor.rs b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs
index d83846f..2d1a405 100644
--- a/src/test/ui/const-generics/array-wrapper-struct-ctor.rs
+++ b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs
@@ -3,6 +3,8 @@
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
 
+#![allow(dead_code)]
+
 struct ArrayStruct<T, const N: usize> {
     data: [T; N],
 }
diff --git a/src/test/ui/const-generics/const-types.rs b/src/test/ui/const-generics/const-types.rs
index 11757cd..bc51881 100644
--- a/src/test/ui/const-generics/const-types.rs
+++ b/src/test/ui/const-generics/const-types.rs
@@ -3,7 +3,7 @@
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
 
-#[allow(dead_code)]
+#![allow(dead_code, unused_variables)]
 
 struct ConstArray<T, const LEN: usize> {
     array: [T; LEN],
diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.rs b/src/test/ui/const-generics/foreign-item-const-parameter.rs
new file mode 100644
index 0000000..4673c86
--- /dev/null
+++ b/src/test/ui/const-generics/foreign-item-const-parameter.rs
@@ -0,0 +1,10 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+extern "C" {
+    fn foo<const X: usize>(); //~ ERROR foreign items may not have const parameters
+
+    fn bar<T, const X: usize>(_: T); //~ ERROR foreign items may not have type or const parameters
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.stderr
new file mode 100644
index 0000000..999feed
--- /dev/null
+++ b/src/test/ui/const-generics/foreign-item-const-parameter.stderr
@@ -0,0 +1,27 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/foreign-item-const-parameter.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0044]: foreign items may not have const parameters
+  --> $DIR/foreign-item-const-parameter.rs:5:5
+   |
+LL |     fn foo<const X: usize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
+   |
+   = help: replace the const parameters with concrete consts
+
+error[E0044]: foreign items may not have type or const parameters
+  --> $DIR/foreign-item-const-parameter.rs:7:5
+   |
+LL |     fn bar<T, const X: usize>(_: T);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
+   |
+   = help: replace the type or const parameters with concrete types or consts
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0044`.
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
index 8f3f916..47b090c 100644
--- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
@@ -11,7 +11,7 @@
    | --------- method `f` not found for this
 ...
 LL |     S.f::<0>();
-   |       ^
+   |       ^ method not found in `S`
 
 error[E0107]: wrong number of const arguments: expected 0, found 1
   --> $DIR/invalid-const-arg-for-type-param.rs:8:9
diff --git a/src/test/ui/const-generics/issue-61422.rs b/src/test/ui/const-generics/issue-61422.rs
index 68e5a52..45d37b6 100644
--- a/src/test/ui/const-generics/issue-61422.rs
+++ b/src/test/ui/const-generics/issue-61422.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
@@ -8,7 +8,7 @@
 fn foo<const SIZE: usize>() {
     let arr: [u8; SIZE] = unsafe {
         #[allow(deprecated)]
-        let mut array: [u8; SIZE] = mem::uninitialized();
+        let array: [u8; SIZE] = mem::uninitialized();
         array
     };
 }
diff --git a/src/test/ui/const-generics/unused-const-param.rs b/src/test/ui/const-generics/unused-const-param.rs
index ee98e5e..8025b3a 100644
--- a/src/test/ui/const-generics/unused-const-param.rs
+++ b/src/test/ui/const-generics/unused-const-param.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs
index a5f685a..ecbcc2a 100644
--- a/src/test/ui/consts/const-err2.rs
+++ b/src/test/ui/consts/const-err2.rs
@@ -5,6 +5,7 @@
 
 #![feature(rustc_attrs)]
 #![allow(exceeding_bitshifts)]
+
 #![deny(const_err)]
 
 fn black_box<T>(_: T) {
@@ -21,7 +22,7 @@
     let d = 42u8 - (42u8 + 1);
     //~^ ERROR const_err
     let _e = [5u8][1];
-    //~^ ERROR const_err
+    //~^ ERROR index out of bounds
     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 659c3af..1d84d44 100644
--- a/src/test/ui/consts/const-err2.stderr
+++ b/src/test/ui/consts/const-err2.stderr
@@ -1,35 +1,35 @@
 error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:15:13
+  --> $DIR/const-err2.rs:16:13
    |
 LL |     let a = -std::i8::MIN;
    |             ^^^^^^^^^^^^^ attempt to negate with overflow
    |
 note: lint level defined here
-  --> $DIR/const-err2.rs:8:9
+  --> $DIR/const-err2.rs:9:9
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:17:13
+  --> $DIR/const-err2.rs:18:13
    |
 LL |     let b = 200u8 + 200u8 + 200u8;
    |             ^^^^^^^^^^^^^ attempt to add with overflow
 
 error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:19:13
+  --> $DIR/const-err2.rs:20:13
    |
 LL |     let c = 200u8 * 4;
    |             ^^^^^^^^^ attempt to multiply with overflow
 
 error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:21:13
+  --> $DIR/const-err2.rs:22:13
    |
 LL |     let d = 42u8 - (42u8 + 1);
    |             ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
 
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/const-err2.rs:23:14
+  --> $DIR/const-err2.rs:24:14
    |
 LL |     let _e = [5u8][1];
    |              ^^^^^^^^
diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs
new file mode 100644
index 0000000..a9cf04c
--- /dev/null
+++ b/src/test/ui/consts/const-err3.rs
@@ -0,0 +1,30 @@
+// needed because negating int::MIN will behave differently between
+// optimized compilation and unoptimized compilation and thus would
+// lead to different lints being emitted
+// compile-flags: -C overflow-checks=on -O
+
+#![feature(rustc_attrs)]
+#![allow(exceeding_bitshifts)]
+
+#![deny(const_err)]
+
+fn black_box<T>(_: T) {
+    unimplemented!()
+}
+
+fn main() {
+    let a = -std::i8::MIN;
+    //~^ ERROR const_err
+    let b = 200u8 + 200u8 + 200u8;
+    //~^ ERROR const_err
+    let c = 200u8 * 4;
+    //~^ ERROR const_err
+    let d = 42u8 - (42u8 + 1);
+    //~^ ERROR const_err
+    let _e = [5u8][1];
+    //~^ ERROR const_err
+    black_box(a);
+    black_box(b);
+    black_box(c);
+    black_box(d);
+}
diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr
new file mode 100644
index 0000000..0602707
--- /dev/null
+++ b/src/test/ui/consts/const-err3.stderr
@@ -0,0 +1,38 @@
+error: attempt to negate with overflow
+  --> $DIR/const-err3.rs:16:13
+   |
+LL |     let a = -std::i8::MIN;
+   |             ^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/const-err3.rs:9:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: attempt to add with overflow
+  --> $DIR/const-err3.rs:18:13
+   |
+LL |     let b = 200u8 + 200u8 + 200u8;
+   |             ^^^^^^^^^^^^^
+
+error: attempt to multiply with overflow
+  --> $DIR/const-err3.rs:20:13
+   |
+LL |     let c = 200u8 * 4;
+   |             ^^^^^^^^^
+
+error: attempt to subtract with overflow
+  --> $DIR/const-err3.rs:22:13
+   |
+LL |     let d = 42u8 - (42u8 + 1);
+   |             ^^^^^^^^^^^^^^^^^
+
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/const-err3.rs:24:14
+   |
+LL |     let _e = [5u8][1];
+   |              ^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/consts/const-err4.stderr b/src/test/ui/consts/const-err4.stderr
index 1feec3c..081b09e 100644
--- a/src/test/ui/consts/const-err4.stderr
+++ b/src/test/ui/consts/const-err4.stderr
@@ -4,7 +4,7 @@
 LL |     Boo = [unsafe { Foo { b: () }.a }; 4][3],
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
index cc5ddb4..a2196db 100644
--- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
+++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
@@ -1,5 +1,6 @@
 // only-x86_64
 
+#[repr(C)]
 union Nonsense {
     u: usize,
     int_32_ref: &'static i32,
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
index 73aca91..e0df787 100644
--- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
+++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
@@ -1,13 +1,13 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const-pointer-values-in-various-types.rs:24:5
+  --> $DIR/const-pointer-values-in-various-types.rs:25:5
    |
 LL |     const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:27:43
+  --> $DIR/const-pointer-values-in-various-types.rs:28:43
    |
 LL |     const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -17,7 +17,7 @@
    = note: `#[deny(const_err)]` on by default
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:30:45
+  --> $DIR/const-pointer-values-in-various-types.rs:31:45
    |
 LL |     const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -25,7 +25,7 @@
    |                                             a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:33:45
+  --> $DIR/const-pointer-values-in-various-types.rs:34:45
    |
 LL |     const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -33,23 +33,23 @@
    |                                             a raw memory access tried to access part of a pointer value as raw bytes
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const-pointer-values-in-various-types.rs:36:5
+  --> $DIR/const-pointer-values-in-various-types.rs:37:5
    |
 LL |     const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const-pointer-values-in-various-types.rs:39:5
+  --> $DIR/const-pointer-values-in-various-types.rs:40:5
    |
 LL |     const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:42:43
+  --> $DIR/const-pointer-values-in-various-types.rs:43:43
    |
 LL |     const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -57,7 +57,7 @@
    |                                           a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:45:45
+  --> $DIR/const-pointer-values-in-various-types.rs:46:45
    |
 LL |     const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -65,7 +65,7 @@
    |                                             a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:48:45
+  --> $DIR/const-pointer-values-in-various-types.rs:49:45
    |
 LL |     const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -73,23 +73,23 @@
    |                                             a raw memory access tried to access part of a pointer value as raw bytes
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const-pointer-values-in-various-types.rs:51:5
+  --> $DIR/const-pointer-values-in-various-types.rs:52:5
    |
 LL |     const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const-pointer-values-in-various-types.rs:54:5
+  --> $DIR/const-pointer-values-in-various-types.rs:55:5
    |
 LL |     const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:57:45
+  --> $DIR/const-pointer-values-in-various-types.rs:58:45
    |
 LL |     const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -97,15 +97,15 @@
    |                                             a raw memory access tried to access part of a pointer value as raw bytes
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const-pointer-values-in-various-types.rs:60:5
+  --> $DIR/const-pointer-values-in-various-types.rs:61:5
    |
 LL |     const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:63:47
+  --> $DIR/const-pointer-values-in-various-types.rs:64:47
    |
 LL |     const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
    |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -113,7 +113,7 @@
    |                                               a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:66:47
+  --> $DIR/const-pointer-values-in-various-types.rs:67:47
    |
 LL |     const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
    |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -121,7 +121,7 @@
    |                                               a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:69:39
+  --> $DIR/const-pointer-values-in-various-types.rs:70:39
    |
 LL |     const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
    |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -129,7 +129,7 @@
    |                                       a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:72:41
+  --> $DIR/const-pointer-values-in-various-types.rs:73:41
    |
 LL |     const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -137,7 +137,7 @@
    |                                         a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:75:41
+  --> $DIR/const-pointer-values-in-various-types.rs:76:41
    |
 LL |     const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -145,15 +145,15 @@
    |                                         a raw memory access tried to access part of a pointer value as raw bytes
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const-pointer-values-in-various-types.rs:78:5
+  --> $DIR/const-pointer-values-in-various-types.rs:79:5
    |
 LL |     const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:81:43
+  --> $DIR/const-pointer-values-in-various-types.rs:82:43
    |
 LL |     const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -161,7 +161,7 @@
    |                                           a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:84:39
+  --> $DIR/const-pointer-values-in-various-types.rs:85:39
    |
 LL |     const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
    |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -169,7 +169,7 @@
    |                                       a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:87:41
+  --> $DIR/const-pointer-values-in-various-types.rs:88:41
    |
 LL |     const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -177,7 +177,7 @@
    |                                         a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:90:41
+  --> $DIR/const-pointer-values-in-various-types.rs:91:41
    |
 LL |     const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -185,15 +185,15 @@
    |                                         a raw memory access tried to access part of a pointer value as raw bytes
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const-pointer-values-in-various-types.rs:93:5
+  --> $DIR/const-pointer-values-in-various-types.rs:94:5
    |
 LL |     const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:96:43
+  --> $DIR/const-pointer-values-in-various-types.rs:97:43
    |
 LL |     const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -201,7 +201,7 @@
    |                                           a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:99:41
+  --> $DIR/const-pointer-values-in-various-types.rs:100:41
    |
 LL |     const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -209,15 +209,15 @@
    |                                         a raw memory access tried to access part of a pointer value as raw bytes
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const-pointer-values-in-various-types.rs:102:5
+  --> $DIR/const-pointer-values-in-various-types.rs:103:5
    |
 LL |     const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:105:43
+  --> $DIR/const-pointer-values-in-various-types.rs:106:43
    |
 LL |     const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -225,7 +225,7 @@
    |                                           a raw memory access tried to access part of a pointer value as raw bytes
 
 error: any use of this value will cause an error
-  --> $DIR/const-pointer-values-in-various-types.rs:108:43
+  --> $DIR/const-pointer-values-in-various-types.rs:109:43
    |
 LL |     const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
diff --git a/src/test/ui/consts/const-eval/const_transmute.rs b/src/test/ui/consts/const-eval/const_transmute.rs
index 0e0e003..f0e1d82 100644
--- a/src/test/ui/consts/const-eval/const_transmute.rs
+++ b/src/test/ui/consts/const-eval/const_transmute.rs
@@ -1,7 +1,9 @@
 // run-pass
 
 #![feature(const_fn_union)]
+#![allow(dead_code)]
 
+#[repr(C)]
 union Transmute<T: Copy, U: Copy> {
     t: T,
     u: U,
diff --git a/src/test/ui/consts/const-eval/dangling.rs b/src/test/ui/consts/const-eval/dangling.rs
new file mode 100644
index 0000000..b5d72d4
--- /dev/null
+++ b/src/test/ui/consts/const-eval/dangling.rs
@@ -0,0 +1,13 @@
+#![feature(const_transmute, const_raw_ptr_deref)]
+
+use std::{mem, usize};
+
+// Make sure we error with the right kind of error on a too large slice.
+const TEST: () = { unsafe { //~ NOTE
+    let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
+    let _val = &*slice; //~ ERROR: any use of this value will cause an error
+    //~^ NOTE: total size is bigger than largest supported object
+    //~^^ on by default
+} };
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/dangling.stderr b/src/test/ui/consts/const-eval/dangling.stderr
new file mode 100644
index 0000000..286de08
--- /dev/null
+++ b/src/test/ui/consts/const-eval/dangling.stderr
@@ -0,0 +1,16 @@
+error: any use of this value will cause an error
+  --> $DIR/dangling.rs:8:16
+   |
+LL | / const TEST: () = { unsafe {
+LL | |     let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
+LL | |     let _val = &*slice;
+   | |                ^^^^^^^ invalid slice: total size is bigger than largest supported object
+LL | |
+LL | |
+LL | | } };
+   | |____-
+   |
+   = note: `#[deny(const_err)]` on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/double_check.rs b/src/test/ui/consts/const-eval/double_check.rs
index 2cf6a54..ff2fff7 100644
--- a/src/test/ui/consts/const-eval/double_check.rs
+++ b/src/test/ui/consts/const-eval/double_check.rs
@@ -8,6 +8,7 @@
     C = 42,
     D = 99,
 }
+#[repr(C)]
 union Union {
     foo: &'static Foo,
     bar: &'static Bar,
diff --git a/src/test/ui/consts/const-eval/double_check2.rs b/src/test/ui/consts/const-eval/double_check2.rs
index dc2b58f..7c222b1 100644
--- a/src/test/ui/consts/const-eval/double_check2.rs
+++ b/src/test/ui/consts/const-eval/double_check2.rs
@@ -6,6 +6,7 @@
     C = 42,
     D = 99,
 }
+#[repr(C)]
 union Union {
     foo: &'static Foo,
     bar: &'static Bar,
diff --git a/src/test/ui/consts/const-eval/double_check2.stderr b/src/test/ui/consts/const-eval/double_check2.stderr
index 2b61d33..28e0922 100644
--- a/src/test/ui/consts/const-eval/double_check2.stderr
+++ b/src/test/ui/consts/const-eval/double_check2.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/double_check2.rs:15:1
+  --> $DIR/double_check2.rs:16:1
    |
 LL | / static FOO: (&Foo, &Bar) = unsafe {(
 LL | |     Union { u8: &BAR }.foo,
@@ -7,7 +7,7 @@
 LL | | )};
    | |___^ type validation failed: encountered 5 at .1.<deref>, but expected a valid enum discriminant
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs
index b0ae746..3f7bab0 100644
--- a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs
+++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs
@@ -2,6 +2,7 @@
 
 fn main() {}
 
+#[repr(C)]
 union Foo {
     u: u32,
     i: i32,
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr
index 5bf43cb..6899b7b 100644
--- a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr
+++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr
@@ -1,5 +1,5 @@
 error[E0658]: unions in const fn are unstable
-  --> $DIR/feature-gate-const_fn_union.rs:11:5
+  --> $DIR/feature-gate-const_fn_union.rs:12:5
    |
 LL |     Foo { u }.i
    |     ^^^^^^^^^^^
diff --git a/src/test/ui/consts/const-eval/issue-49296.rs b/src/test/ui/consts/const-eval/issue-49296.rs
index a7c3c53..c6caeef 100644
--- a/src/test/ui/consts/const-eval/issue-49296.rs
+++ b/src/test/ui/consts/const-eval/issue-49296.rs
@@ -4,6 +4,7 @@
 #![feature(const_fn_union)]
 
 const unsafe fn transmute<T: Copy, U: Copy>(t: T) -> U {
+    #[repr(C)]
     union Transmute<T: Copy, U: Copy> {
         from: T,
         to: U,
diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr
index 7a4bba8..48809e0 100644
--- a/src/test/ui/consts/const-eval/issue-49296.stderr
+++ b/src/test/ui/consts/const-eval/issue-49296.stderr
@@ -1,5 +1,5 @@
 error: any use of this value will cause an error
-  --> $DIR/issue-49296.rs:18:16
+  --> $DIR/issue-49296.rs:19:16
    |
 LL | const X: u64 = *wat(42);
    | ---------------^^^^^^^^-
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs
index 88181cb..3edd4e0 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs
@@ -2,6 +2,7 @@
 
 #![allow(const_err)]
 
+#[repr(C)]
 union Bar {
     a: &'static u8,
     b: usize,
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
index 519ba7d..6618f1c 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promoted_const_fn_fail.rs:20:27
+  --> $DIR/promoted_const_fn_fail.rs:21:27
    |
 LL |     let x: &'static u8 = &(bar() + 1);
    |            -----------    ^^^^^^^^^^^ creates a temporary which is freed while still in use
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs
index 061ab7e..7887e42 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs
@@ -2,6 +2,7 @@
 
 #![deny(const_err)]
 
+#[repr(C)]
 union Bar {
     a: &'static u8,
     b: usize,
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
index 987d230..5f9f3bd 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promoted_const_fn_fail_deny_const_err.rs:21:27
+  --> $DIR/promoted_const_fn_fail_deny_const_err.rs:22:27
    |
 LL |     let x: &'static u8 = &(bar() + 1);
    |            -----------    ^^^^^^^^^^^ creates a temporary which is freed while still in use
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs
index cd98973..4594139 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs
@@ -5,7 +5,7 @@
 fn main() {
     println!("{}", 0u32 - 1);
     let _x = 0u32 - 1;
-    //~^ ERROR this expression will panic at runtime [const_err]
+    //~^ 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]
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs
new file mode 100644
index 0000000..7adb394
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_errors2.rs
@@ -0,0 +1,22 @@
+// compile-flags: -C overflow-checks=on -O
+
+#![deny(const_err)]
+
+fn main() {
+    println!("{}", 0u32 - 1);
+    //~^ ERROR attempt to subtract with overflow
+    let _x = 0u32 - 1;
+    //~^ 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]
+    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]
+    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
new file mode 100644
index 0000000..2819e6e
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr
@@ -0,0 +1,68 @@
+error: attempt to subtract with overflow
+  --> $DIR/promoted_errors2.rs:6:20
+   |
+LL |     println!("{}", 0u32 - 1);
+   |                    ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/promoted_errors2.rs:3:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: attempt to subtract with overflow
+  --> $DIR/promoted_errors2.rs:8:14
+   |
+LL |     let _x = 0u32 - 1;
+   |              ^^^^^^^^
+
+error: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:10:20
+   |
+LL |     println!("{}", 1/(1-1));
+   |                    ^^^^^^^
+
+error: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors2.rs:10:20
+   |
+LL |     println!("{}", 1/(1-1));
+   |                    ^^^^^^^ attempt to divide by zero
+
+error: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:13:14
+   |
+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
+   |
+LL |     println!("{}", 1/(false as u32));
+   |                    ^^^^^^^^^^^^^^^^
+
+error: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors2.rs:16:20
+   |
+LL |     println!("{}", 1/(false as u32));
+   |                    ^^^^^^^^^^^^^^^^ attempt to divide by zero
+
+error: attempt to divide by zero
+  --> $DIR/promoted_errors2.rs:19: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
+
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.rs b/src/test/ui/consts/const-eval/ref_to_int_match.rs
index b6a2ed1..45ce040 100644
--- a/src/test/ui/consts/const-eval/ref_to_int_match.rs
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.rs
@@ -9,6 +9,7 @@
     }
 }
 
+#[repr(C)]
 union Foo {
     f: Int,
     r: &'static u32,
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.stderr
index f8eafed..b72a5b8 100644
--- a/src/test/ui/consts/const-eval/ref_to_int_match.stderr
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.stderr
@@ -1,10 +1,10 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ref_to_int_match.rs:23:1
+  --> $DIR/ref_to_int_match.rs:24:1
    |
 LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: could not evaluate constant pattern
   --> $DIR/ref_to_int_match.rs:7:14
diff --git a/src/test/ui/consts/const-eval/transmute-const.stderr b/src/test/ui/consts/const-eval/transmute-const.stderr
index cacf863..47f89fc 100644
--- a/src/test/ui/consts/const-eval/transmute-const.stderr
+++ b/src/test/ui/consts/const-eval/transmute-const.stderr
@@ -4,7 +4,7 @@
 LL | static FOO: bool = unsafe { mem::transmute(3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected something less or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs
index d4b2220..483285a 100644
--- a/src/test/ui/consts/const-eval/ub-enum.rs
+++ b/src/test/ui/consts/const-eval/ub-enum.rs
@@ -10,6 +10,7 @@
 enum Enum {
     A = 0,
 }
+#[repr(C)]
 union TransmuteEnum {
     in1: &'static u8,
     in2: usize,
@@ -35,6 +36,7 @@
     A = 2,
 }
 
+#[repr(C)]
 union TransmuteEnum2 {
     in1: usize,
     in2: &'static u8,
@@ -60,6 +62,7 @@
 
 // Invalid enum field content (mostly to test printing of paths for enum tuple
 // variants and tuples).
+#[repr(C)]
 union TransmuteChar {
     a: u32,
     b: char,
diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr
index 8ecb1aa..8ebc9db 100644
--- a/src/test/ui/consts/const-eval/ub-enum.stderr
+++ b/src/test/ui/consts/const-eval/ub-enum.stderr
@@ -1,74 +1,74 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:22:1
+  --> $DIR/ub-enum.rs:23:1
    |
 LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:25:1
+  --> $DIR/ub-enum.rs:26:1
    |
 LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:28:1
+  --> $DIR/ub-enum.rs:29:1
    |
 LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 0
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:46:1
-   |
-LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:48:1
    |
-LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:50:1
    |
+LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-enum.rs:52:1
+   |
 LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 2
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:54:1
+  --> $DIR/ub-enum.rs:56:1
    |
 LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:58:1
+  --> $DIR/ub-enum.rs:60:1
    |
 LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:68:1
+  --> $DIR/ub-enum.rs:71:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs
index 9edae19..8ce64ce 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.rs
+++ b/src/test/ui/consts/const-eval/ub-nonnull.rs
@@ -24,6 +24,7 @@
 const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
 //~^ ERROR it is undefined behavior to use this value
 
+#[repr(C)]
 union Transmute {
     uninit: (),
     out: NonZeroU8,
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
index 7b3c97e..80d80a9 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr
@@ -4,7 +4,7 @@
 LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: any use of this value will cause an error
   --> $DIR/ub-nonnull.rs:18:29
@@ -30,7 +30,7 @@
 LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-nonnull.rs:24:1
@@ -38,31 +38,31 @@
 LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:31:1
+  --> $DIR/ub-nonnull.rs:32:1
    |
 LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:39:1
+  --> $DIR/ub-nonnull.rs:40:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:45:1
+  --> $DIR/ub-nonnull.rs:46:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs
index bbab85c..03ac12c 100644
--- a/src/test/ui/consts/const-eval/ub-ref.rs
+++ b/src/test/ui/consts/const-eval/ub-ref.rs
@@ -11,6 +11,9 @@
 const NULL: &u16 = unsafe { mem::transmute(0usize) };
 //~^ ERROR it is undefined behavior to use this value
 
+// It is very important that we reject this: We do promote `&(4 * REF_AS_USIZE)`,
+// but that would fail to compile; so we ended up breaking user code that would
+// have worked fine had we not promoted.
 const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
 //~^ ERROR it is undefined behavior to use this value
 
diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr
index f170295..01bde41 100644
--- a/src/test/ui/consts/const-eval/ub-ref.stderr
+++ b/src/test/ui/consts/const-eval/ub-ref.stderr
@@ -4,7 +4,7 @@
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1)
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref.rs:11:1
@@ -12,31 +12,31 @@
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref.rs:14:1
-   |
-LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref.rs:17:1
    |
-LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
+LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref.rs:20:1
    |
+LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-ref.rs:23:1
+   |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (created from integer)
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs
index 42cba02..d2745d7 100644
--- a/src/test/ui/consts/const-eval/ub-uninhabit.rs
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs
@@ -6,6 +6,7 @@
 #[derive(Copy, Clone)]
 enum Bar {}
 
+#[repr(C)]
 union TransmuteUnion<A: Clone + Copy, B: Clone + Copy> {
     a: A,
     b: B,
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr
index c8842ec..3877f3c 100644
--- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr
@@ -1,26 +1,26 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-uninhabit.rs:14:1
+  --> $DIR/ub-uninhabit.rs:15:1
    |
 LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-uninhabit.rs:17:1
+  --> $DIR/ub-uninhabit.rs:18:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-uninhabit.rs:20:1
+  --> $DIR/ub-uninhabit.rs:21:1
    |
 LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/const-eval/ub-upvars.stderr b/src/test/ui/consts/const-eval/ub-upvars.stderr
index f8273ba..ea6ab3a 100644
--- a/src/test/ui/consts/const-eval/ub-upvars.stderr
+++ b/src/test/ui/consts/const-eval/ub-upvars.stderr
@@ -8,7 +8,7 @@
 LL | | };
    | |__^ type validation failed: encountered 0 at .<deref>.<dyn-downcast>.<closure-var(bad_ref)>, but expected something greater or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
index 765ed60..1f810c4 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
@@ -7,6 +7,7 @@
 // normalize-stderr-test "allocation \d+" -> "allocation N"
 // normalize-stderr-test "size \d+" -> "size N"
 
+#[repr(C)]
 union BoolTransmute {
   val: u8,
   bl: bool,
@@ -26,6 +27,7 @@
     len: &'static u8,
 }
 
+#[repr(C)]
 union SliceTransmute {
     repr: SliceRepr,
     bad: BadSliceRepr,
@@ -58,6 +60,7 @@
     vtable: usize,
 }
 
+#[repr(C)]
 union DynTransmute {
     repr: DynRepr,
     repr2: DynRepr2,
@@ -91,10 +94,10 @@
 //~^ ERROR it is undefined behavior to use this value
 
 // invalid UTF-8
-const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
 //~^ ERROR it is undefined behavior to use this value
 // invalid UTF-8 in user-defined str-like
-const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
 //~^ ERROR it is undefined behavior to use this value
 
 // # slice
@@ -111,16 +114,16 @@
 //~^ ERROR it is undefined behavior to use this value
 
 // bad data *inside* the slice
-const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
 //~^ ERROR it is undefined behavior to use this value
 
 // good MySliceBool
-const I1: &MySliceBool = &MySlice(true, [false]);
+const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]);
 // bad: sized field is not okay
-const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
 //~^ ERROR it is undefined behavior to use this value
 // bad: unsized part is not okay
-const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
 //~^ ERROR it is undefined behavior to use this value
 
 // # raw slice
@@ -132,17 +135,17 @@
 
 // # trait object
 // bad trait object
-const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
 //~^ ERROR it is undefined behavior to use this value
 // bad trait object
-const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
 //~^ ERROR it is undefined behavior to use this value
 // bad trait object
-const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
 //~^ ERROR it is undefined behavior to use this value
 
 // bad data *inside* the trait object
-const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
 //~^ ERROR it is undefined behavior to use this value
 
 // # raw trait object
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
index 88d8af8..9134ef5 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
@@ -1,146 +1,146 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:84:1
+  --> $DIR/ub-wide-ptr.rs:87:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds)
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:87:1
-   |
-LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:90:1
    |
+LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:93:1
+   |
 LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:94:1
-   |
-LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:97:1
    |
-LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
+LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:104:1
+  --> $DIR/ub-wide-ptr.rs:100:1
    |
-LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata
+LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:107:1
    |
-LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds)
+LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:110:1
    |
+LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds)
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:113:1
+   |
 LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:114:1
+  --> $DIR/ub-wide-ptr.rs:117:1
    |
-LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something less or equal to 1
+LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[0], but expected something less or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:120:1
-   |
-LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something less or equal to 1
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:123:1
    |
-LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something less or equal to 1
+LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.0, but expected something less or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:130:1
+  --> $DIR/ub-wide-ptr.rs:126:1
+   |
+LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.1[0], but expected something less or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:133:1
    |
 LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:135:1
-   |
-LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:138:1
    |
-LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:141:1
    |
-LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
+LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:145:1
+  --> $DIR/ub-wide-ptr.rs:144:1
    |
-LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected something less or equal to 1
+LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:149:1
+  --> $DIR/ub-wide-ptr.rs:148:1
+   |
+LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected something less or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:152:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:151:1
+  --> $DIR/ub-wide-ptr.rs:154:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.rs b/src/test/ui/consts/const-eval/union-const-eval-field.rs
index 56f3ef3..7f29a5b 100644
--- a/src/test/ui/consts/const-eval/union-const-eval-field.rs
+++ b/src/test/ui/consts/const-eval/union-const-eval-field.rs
@@ -4,6 +4,7 @@
 type Field2 = f32;
 type Field3 = i64;
 
+#[repr(C)]
 union DummyUnion {
     field1: Field1,
     field2: Field2,
diff --git a/src/test/ui/consts/const-eval/union-const-eval-field.stderr b/src/test/ui/consts/const-eval/union-const-eval-field.stderr
index 4a53337..9193bd9 100644
--- a/src/test/ui/consts/const-eval/union-const-eval-field.stderr
+++ b/src/test/ui/consts/const-eval/union-const-eval-field.stderr
@@ -1,10 +1,10 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/union-const-eval-field.rs:27:5
+  --> $DIR/union-const-eval-field.rs:28:5
    |
 LL |     const FIELD3: Field3 = unsafe { UNION.field3 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/union-ice.rs b/src/test/ui/consts/const-eval/union-ice.rs
index 33736b3..5a14c7f 100644
--- a/src/test/ui/consts/const-eval/union-ice.rs
+++ b/src/test/ui/consts/const-eval/union-ice.rs
@@ -3,6 +3,7 @@
 type Field1 = i32;
 type Field3 = i64;
 
+#[repr(C)]
 union DummyUnion {
     field1: Field1,
     field3: Field3,
diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr
index b25cb8c..476f365 100644
--- a/src/test/ui/consts/const-eval/union-ice.stderr
+++ b/src/test/ui/consts/const-eval/union-ice.stderr
@@ -1,13 +1,13 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/union-ice.rs:13:1
+  --> $DIR/union-ice.rs:14:1
    |
 LL | const FIELD3: Field3 = unsafe { UNION.field3 };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/union-ice.rs:15:1
+  --> $DIR/union-ice.rs:16:1
    |
 LL | / const FIELD_PATH: Struct = Struct {
 LL | |     a: 42,
@@ -15,10 +15,10 @@
 LL | | };
    | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain (non-pointer) bytes
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/union-ice.rs:25:1
+  --> $DIR/union-ice.rs:26:1
    |
 LL | / const FIELD_PATH2: Struct2 = Struct2 {
 LL | |     b: [
@@ -29,7 +29,7 @@
 LL | | };
    | |__^ type validation failed: encountered undefined bytes at .b[1]
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/const-eval/union-ub.rs b/src/test/ui/consts/const-eval/union-ub.rs
index cf43614..848826e 100644
--- a/src/test/ui/consts/const-eval/union-ub.rs
+++ b/src/test/ui/consts/const-eval/union-ub.rs
@@ -1,5 +1,6 @@
 #![allow(const_err)] // make sure we cannot allow away the errors tested here
 
+#[repr(C)]
 union DummyUnion {
     u8: u8,
     bool: bool,
@@ -14,11 +15,13 @@
 }
 
 #[derive(Copy, Clone)]
+#[repr(C)]
 union Foo {
     a: bool,
     b: Enum,
 }
 
+#[repr(C)]
 union Bar {
     foo: Foo,
     u8: u8,
diff --git a/src/test/ui/consts/const-eval/union-ub.stderr b/src/test/ui/consts/const-eval/union-ub.stderr
index 7baa55b..fa67bc0 100644
--- a/src/test/ui/consts/const-eval/union-ub.stderr
+++ b/src/test/ui/consts/const-eval/union-ub.stderr
@@ -1,10 +1,10 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/union-ub.rs:28:1
+  --> $DIR/union-ub.rs:31:1
    |
 LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something less or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/union_promotion.rs b/src/test/ui/consts/const-eval/union_promotion.rs
index d356651..7167f88 100644
--- a/src/test/ui/consts/const-eval/union_promotion.rs
+++ b/src/test/ui/consts/const-eval/union_promotion.rs
@@ -1,5 +1,6 @@
 #![allow(const_err)]
 
+#[repr(C)]
 union Foo {
     a: &'static u32,
     b: usize,
diff --git a/src/test/ui/consts/const-eval/union_promotion.stderr b/src/test/ui/consts/const-eval/union_promotion.stderr
index b530c02..ed186e3 100644
--- a/src/test/ui/consts/const-eval/union_promotion.stderr
+++ b/src/test/ui/consts/const-eval/union_promotion.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/union_promotion.rs:9:29
+  --> $DIR/union_promotion.rs:10:29
    |
 LL |       let x: &'static bool = &unsafe {
    |  ____________-------------____^
diff --git a/src/test/ui/consts/const-eval/valid-const.rs b/src/test/ui/consts/const-eval/valid-const.rs
index 30bd472..65c642d 100644
--- a/src/test/ui/consts/const-eval/valid-const.rs
+++ b/src/test/ui/consts/const-eval/valid-const.rs
@@ -1,7 +1,8 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 // Some constants that *are* valid
 #![feature(const_transmute)]
+#![deny(const_err)]
 
 use std::mem;
 use std::ptr::NonNull;
diff --git a/src/test/ui/consts/const-int-overflowing-rpass.rs b/src/test/ui/consts/const-int-overflowing-rpass.rs
index b619c79..9be87a6 100644
--- a/src/test/ui/consts/const-int-overflowing-rpass.rs
+++ b/src/test/ui/consts/const-int-overflowing-rpass.rs
@@ -18,6 +18,10 @@
 const NEG_A: (u32, bool) = 0u32.overflowing_neg();
 const NEG_B: (u32, bool) = core::u32::MAX.overflowing_neg();
 
+const ABS_POS: (i32, bool) = 10i32.overflowing_abs();
+const ABS_NEG: (i32, bool) = (-10i32).overflowing_abs();
+const ABS_MIN: (i32, bool) = i32::min_value().overflowing_abs();
+
 fn main() {
     assert_eq!(ADD_A, (7, false));
     assert_eq!(ADD_B, (0, true));
@@ -36,4 +40,8 @@
 
     assert_eq!(NEG_A, (0, false));
     assert_eq!(NEG_B, (1, true));
+
+    assert_eq!(ABS_POS, (10, false));
+    assert_eq!(ABS_NEG, (10, false));
+    assert_eq!(ABS_MIN, (i32::min_value(), true));
 }
diff --git a/src/test/ui/consts/const-int-sign-rpass.rs b/src/test/ui/consts/const-int-sign-rpass.rs
index 05726cb..dc46fce 100644
--- a/src/test/ui/consts/const-int-sign-rpass.rs
+++ b/src/test/ui/consts/const-int-sign-rpass.rs
@@ -11,6 +11,9 @@
 const SIGNUM_NIL: i32 = 0i32.signum();
 const SIGNUM_NEG: i32 = (-42i32).signum();
 
+const ABS_A: i32 = 10i32.abs();
+const ABS_B: i32 = (-10i32).abs();
+
 fn main() {
     assert!(NEGATIVE_A);
     assert!(!NEGATIVE_B);
@@ -20,4 +23,7 @@
     assert_eq!(SIGNUM_POS, 1);
     assert_eq!(SIGNUM_NIL, 0);
     assert_eq!(SIGNUM_NEG, -1);
+
+    assert_eq!(ABS_A, 10);
+    assert_eq!(ABS_B, 10);
 }
diff --git a/src/test/ui/consts/const-int-wrapping-rpass.rs b/src/test/ui/consts/const-int-wrapping-rpass.rs
index 73147d7..2bbad99 100644
--- a/src/test/ui/consts/const-int-wrapping-rpass.rs
+++ b/src/test/ui/consts/const-int-wrapping-rpass.rs
@@ -18,6 +18,10 @@
 const NEG_A: u32 = 5u32.wrapping_neg();
 const NEG_B: u32 = 1234567890u32.wrapping_neg();
 
+const ABS_POS: i32 = 10i32.wrapping_abs();
+const ABS_NEG: i32 = (-10i32).wrapping_abs();
+const ABS_MIN: i32 = i32::min_value().wrapping_abs();
+
 fn main() {
     assert_eq!(ADD_A, 255);
     assert_eq!(ADD_B, 199);
@@ -36,4 +40,8 @@
 
     assert_eq!(NEG_A, 4294967291);
     assert_eq!(NEG_B, 3060399406);
+
+    assert_eq!(ABS_POS, 10);
+    assert_eq!(ABS_NEG, 10);
+    assert_eq!(ABS_MIN, i32::min_value());
 }
diff --git a/src/test/ui/consts/const-labeled-break.rs b/src/test/ui/consts/const-labeled-break.rs
index 36e308a..7cdbb22 100644
--- a/src/test/ui/consts/const-labeled-break.rs
+++ b/src/test/ui/consts/const-labeled-break.rs
@@ -1,4 +1,4 @@
-// run-pass
+// build-pass
 
 // Using labeled break in a while loop has caused an illegal instruction being
 // generated, and an ICE later.
diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr
index 3bcb50c..24d2e3c 100644
--- a/src/test/ui/consts/const-match-check.eval1.stderr
+++ b/src/test/ui/consts/const-match-check.eval1.stderr
@@ -1,8 +1,8 @@
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
+error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
   --> $DIR/const-match-check.rs:25:15
    |
 LL |     A = { let 0 = 0; 0 },
-   |               ^ pattern `std::i32::MIN..=-1i32` not covered
+   |               ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr
index e292e1c..5d59d06 100644
--- a/src/test/ui/consts/const-match-check.eval2.stderr
+++ b/src/test/ui/consts/const-match-check.eval2.stderr
@@ -1,8 +1,8 @@
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
+error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
   --> $DIR/const-match-check.rs:31:24
    |
 LL |     let x: [i32; { let 0 = 0; 0 }] = [];
-   |                        ^ pattern `std::i32::MIN..=-1i32` not covered
+   |                        ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr
index 8a9fbde..6d74c26 100644
--- a/src/test/ui/consts/const-match-check.matchck.stderr
+++ b/src/test/ui/consts/const-match-check.matchck.stderr
@@ -1,26 +1,26 @@
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
+error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
   --> $DIR/const-match-check.rs:4:22
    |
 LL | const X: i32 = { let 0 = 0; 0 };
-   |                      ^ pattern `std::i32::MIN..=-1i32` not covered
+   |                      ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
 
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
+error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
   --> $DIR/const-match-check.rs:8:23
    |
 LL | static Y: i32 = { let 0 = 0; 0 };
-   |                       ^ pattern `std::i32::MIN..=-1i32` not covered
+   |                       ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
 
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
+error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
   --> $DIR/const-match-check.rs:13:26
    |
 LL |     const X: i32 = { let 0 = 0; 0 };
-   |                          ^ pattern `std::i32::MIN..=-1i32` not covered
+   |                          ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
 
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
+error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
   --> $DIR/const-match-check.rs:19:26
    |
 LL |     const X: i32 = { let 0 = 0; 0 };
-   |                          ^ pattern `std::i32::MIN..=-1i32` not covered
+   |                          ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/consts/const-pattern-irrefutable.rs b/src/test/ui/consts/const-pattern-irrefutable.rs
index d3f7be1..60e16aa 100644
--- a/src/test/ui/consts/const-pattern-irrefutable.rs
+++ b/src/test/ui/consts/const-pattern-irrefutable.rs
@@ -9,8 +9,8 @@
 const a: u8 = 2;
 
 fn main() {
-    let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered
-    let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered
-    let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered
+    let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX
+    let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX
+    let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX
     fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
 }
diff --git a/src/test/ui/consts/const-pattern-irrefutable.stderr b/src/test/ui/consts/const-pattern-irrefutable.stderr
index 48fe24d..06f5e90 100644
--- a/src/test/ui/consts/const-pattern-irrefutable.stderr
+++ b/src/test/ui/consts/const-pattern-irrefutable.stderr
@@ -1,16 +1,16 @@
-error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered
+error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered
   --> $DIR/const-pattern-irrefutable.rs:12:9
    |
 LL |     let a = 4;
    |         ^ interpreted as a constant pattern, not new variable
 
-error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered
+error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered
   --> $DIR/const-pattern-irrefutable.rs:13:9
    |
 LL |     let c = 4;
    |         ^ interpreted as a constant pattern, not new variable
 
-error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered
+error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered
   --> $DIR/const-pattern-irrefutable.rs:14:9
    |
 LL |     let d = 4;
diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr
index fdba359..1ae39e7 100644
--- a/src/test/ui/consts/const-size_of-cycle.stderr
+++ b/src/test/ui/consts/const-size_of-cycle.stderr
@@ -14,6 +14,11 @@
    |
 LL |     intrinsics::size_of::<T>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
+  --> $SRC_DIR/libcore/intrinsics.rs:LL:COL
+   |
+LL |     pub fn size_of<T>() -> usize;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires computing layout of `Foo`...
    = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
    = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
diff --git a/src/test/ui/consts/const_let_refutable.rs b/src/test/ui/consts/const_let_refutable.rs
index 7b3a591..d48d594 100644
--- a/src/test/ui/consts/const_let_refutable.rs
+++ b/src/test/ui/consts/const_let_refutable.rs
@@ -2,6 +2,6 @@
 
 const fn slice([a, b]: &[i32]) -> i32 { //~ ERROR refutable pattern in function argument
     a + b //~ ERROR can only call other `const fn` within a `const fn`
-    //~^ ERROR use of possibly uninitialized variable: `a`
-    //~| ERROR use of possibly uninitialized variable: `b`
+    //~^ ERROR use of possibly-uninitialized variable: `a`
+    //~| ERROR use of possibly-uninitialized variable: `b`
 }
diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr
index a61c9b0..7f15f02 100644
--- a/src/test/ui/consts/const_let_refutable.stderr
+++ b/src/test/ui/consts/const_let_refutable.stderr
@@ -1,8 +1,8 @@
-error[E0005]: refutable pattern in function argument: `&[]` not covered
+error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _]` not covered
   --> $DIR/const_let_refutable.rs:3:16
    |
 LL | const fn slice([a, b]: &[i32]) -> i32 {
-   |                ^^^^^^ pattern `&[]` not covered
+   |                ^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _]` not covered
 
 error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn`
   --> $DIR/const_let_refutable.rs:4:5
@@ -13,17 +13,17 @@
    = 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[E0381]: use of possibly uninitialized variable: `a`
+error[E0381]: use of possibly-uninitialized variable: `a`
   --> $DIR/const_let_refutable.rs:4:5
    |
 LL |     a + b
-   |     ^ use of possibly uninitialized `a`
+   |     ^ use of possibly-uninitialized `a`
 
-error[E0381]: use of possibly uninitialized variable: `b`
+error[E0381]: use of possibly-uninitialized variable: `b`
   --> $DIR/const_let_refutable.rs:4:9
    |
 LL |     a + b
-   |         ^ use of possibly uninitialized `b`
+   |         ^ use of possibly-uninitialized `b`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/consts/issue-64059-2.rs b/src/test/ui/consts/issue-64059-2.rs
new file mode 100644
index 0000000..38911c3
--- /dev/null
+++ b/src/test/ui/consts/issue-64059-2.rs
@@ -0,0 +1,6 @@
+// compile-flags: -C overflow-checks=on -O
+// run-pass
+
+fn main() {
+    let _ = -(-0.0);
+}
diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs
new file mode 100644
index 0000000..c4c895f
--- /dev/null
+++ b/src/test/ui/consts/issue-64059.rs
@@ -0,0 +1,5 @@
+// run-pass
+
+fn main() {
+    let _ = -(-0.0);
+}
diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr
index 158581f..bf0bd3a 100644
--- a/src/test/ui/consts/match_ice.stderr
+++ b/src/test/ui/consts/match_ice.stderr
@@ -7,6 +7,9 @@
 error[E0004]: non-exhaustive patterns: `&T` not covered
   --> $DIR/match_ice.rs:15:11
    |
+LL | struct T;
+   | --------- `T` defined here
+...
 LL |     match K {
    |           ^ pattern `&T` not covered
    |
diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
index 5fb9253..8b17f68 100644
--- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
@@ -14,8 +14,9 @@
 impl Foo<u32> for () {
     const X: u32 = 42;
 }
+
 impl Foo<Vec<u32>> for String {
-    const X: Vec<u32> = Vec::new(); //~ ERROR not yet stable as a const fn
+    const X: Vec<u32> = Vec::new();
 }
 
 impl Bar<u32, ()> for () {}
diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
index c56ebf6..5bc7b70 100644
--- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
@@ -4,13 +4,5 @@
 LL |     const F: u32 = (U::X, 42).1;
    |                    ^^^^^^^^^^ constants cannot evaluate destructors
 
-error: `std::vec::Vec::<T>::new` is not yet stable as a const fn
-  --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:18:25
-   |
-LL |     const X: Vec<u32> = Vec::new();
-   |                         ^^^^^^^^^^
-   |
-   = help: add `#![feature(const_vec_new)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs
new file mode 100644
index 0000000..b476e04
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+
+#![feature(const_raw_ptr_deref)]
+#![deny(const_err)]
+
+use std::cell::UnsafeCell;
+
+// make sure we do not just intern this as mutable
+const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
+
+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
+    }
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
new file mode 100644
index 0000000..507d4823
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
@@ -0,0 +1,27 @@
+warning: skipping const checks
+  --> $DIR/mutable_const.rs:14:9
+   |
+LL |         *MUTABLE_BEHIND_RAW = 99
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: any use of this value will cause an error
+  --> $DIR/mutable_const.rs:14: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
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
index 82569e2..28cf353 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
@@ -6,7 +6,7 @@
 
 thread 'rustc' panicked at 'assertion failed: `(left != right)`
   left: `Const`,
- right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites may arbitrarily decide to change, too.', src/librustc_mir/interpret/intern.rs:LL:CC
+ right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites could observe that mutation.', src/librustc_mir/interpret/intern.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
 error: internal compiler error: unexpected panic
diff --git a/src/test/ui/consts/packed_pattern.stderr b/src/test/ui/consts/packed_pattern.stderr
new file mode 100644
index 0000000..9b7daf2
--- /dev/null
+++ b/src/test/ui/consts/packed_pattern.stderr
@@ -0,0 +1,8 @@
+warning: unreachable pattern
+  --> $DIR/packed_pattern.rs:16:9
+   |
+LL |         FOO => unreachable!(),
+   |         ^^^
+   |
+   = note: `#[warn(unreachable_patterns)]` on by default
+
diff --git a/src/test/ui/consts/packed_pattern2.stderr b/src/test/ui/consts/packed_pattern2.stderr
new file mode 100644
index 0000000..6cc0225
--- /dev/null
+++ b/src/test/ui/consts/packed_pattern2.stderr
@@ -0,0 +1,8 @@
+warning: unreachable pattern
+  --> $DIR/packed_pattern2.rs:24:9
+   |
+LL |         FOO => unreachable!(),
+   |         ^^^
+   |
+   = note: `#[warn(unreachable_patterns)]` on by default
+
diff --git a/src/test/ui/consts/std/alloc.stderr b/src/test/ui/consts/std/alloc.stderr
index 74a8f3d..26b7a24 100644
--- a/src/test/ui/consts/std/alloc.stderr
+++ b/src/test/ui/consts/std/alloc.stderr
@@ -4,7 +4,7 @@
 LL | const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0 at .align_, but expected something greater or equal to 1
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr
index eef7942..0733a51 100644
--- a/src/test/ui/consts/too_generic_eval_ice.stderr
+++ b/src/test/ui/consts/too_generic_eval_ice.stderr
@@ -14,32 +14,28 @@
 error[E0277]: the size for values of type `A` cannot be known at compilation time
   --> $DIR/too_generic_eval_ice.rs:7:13
    |
+LL | pub struct Foo<A, B>(A, B);
+   | --------------------------- required by `Foo`
+...
 LL |         [5; Self::HOST_SIZE] == [6; 0]
    |             ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `A`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where A: std::marker::Sized` bound
-note: required by `Foo`
-  --> $DIR/too_generic_eval_ice.rs:1:1
-   |
-LL | pub struct Foo<A, B>(A, B);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `B` cannot be known at compilation time
   --> $DIR/too_generic_eval_ice.rs:7:13
    |
+LL | pub struct Foo<A, B>(A, B);
+   | --------------------------- required by `Foo`
+...
 LL |         [5; Self::HOST_SIZE] == [6; 0]
    |             ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `B`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where B: std::marker::Sized` bound
-note: required by `Foo`
-  --> $DIR/too_generic_eval_ice.rs:1:1
-   |
-LL | pub struct Foo<A, B>(A, B);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr
index 7a7d816..c4c7a33 100644
--- a/src/test/ui/consts/validate_never_arrays.stderr
+++ b/src/test/ui/consts/validate_never_arrays.stderr
@@ -4,7 +4,7 @@
 LL | const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/continue-after-missing-main.nll.stderr b/src/test/ui/continue-after-missing-main.nll.stderr
index aceabf3..b94c365 100644
--- a/src/test/ui/continue-after-missing-main.nll.stderr
+++ b/src/test/ui/continue-after-missing-main.nll.stderr
@@ -1,6 +1,14 @@
 error[E0601]: `main` function not found in crate `continue_after_missing_main`
+  --> $DIR/continue-after-missing-main.rs:1:1
    |
-   = note: consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
+LL | / #![allow(dead_code)]
+LL | |
+LL | | // error-pattern:`main` function not found in crate
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/continue-after-missing-main.stderr b/src/test/ui/continue-after-missing-main.stderr
index cc5f876..d764e7d 100644
--- a/src/test/ui/continue-after-missing-main.stderr
+++ b/src/test/ui/continue-after-missing-main.stderr
@@ -1,6 +1,14 @@
 error[E0601]: `main` function not found in crate `continue_after_missing_main`
+  --> $DIR/continue-after-missing-main.rs:1:1
    |
-   = note: consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
+LL | / #![allow(dead_code)]
+LL | |
+LL | | // error-pattern:`main` function not found in crate
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
 
 error[E0623]: lifetime mismatch
   --> $DIR/continue-after-missing-main.rs:30:56
diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr
index cceb9e3..054bd09 100644
--- a/src/test/ui/copy-a-resource.stderr
+++ b/src/test/ui/copy-a-resource.stderr
@@ -5,7 +5,7 @@
    | ---------- method `clone` not found for this
 ...
 LL |     let _y = x.clone();
-   |                ^^^^^
+   |                ^^^^^ method not found in `Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
diff --git a/src/test/ui/custom_attribute.rs b/src/test/ui/custom_attribute.rs
index 13c873c..4957184 100644
--- a/src/test/ui/custom_attribute.rs
+++ b/src/test/ui/custom_attribute.rs
@@ -1,9 +1,9 @@
 #![feature(stmt_expr_attributes)]
 
-#[foo] //~ ERROR cannot find attribute macro `foo` in this scope
+#[foo] //~ ERROR cannot find attribute `foo` in this scope
 fn main() {
-    #[foo] //~ ERROR cannot find attribute macro `foo` in this scope
+    #[foo] //~ ERROR cannot find attribute `foo` in this scope
     let x = ();
-    #[foo] //~ ERROR cannot find attribute macro `foo` in this scope
+    #[foo] //~ ERROR cannot find attribute `foo` in this scope
     x
 }
diff --git a/src/test/ui/custom_attribute.stderr b/src/test/ui/custom_attribute.stderr
index b4f9f3f..4023892 100644
--- a/src/test/ui/custom_attribute.stderr
+++ b/src/test/ui/custom_attribute.stderr
@@ -1,16 +1,16 @@
-error: cannot find attribute macro `foo` in this scope
+error: cannot find attribute `foo` in this scope
   --> $DIR/custom_attribute.rs:3:3
    |
 LL | #[foo]
    |   ^^^
 
-error: cannot find attribute macro `foo` in this scope
+error: cannot find attribute `foo` in this scope
   --> $DIR/custom_attribute.rs:5:7
    |
 LL |     #[foo]
    |       ^^^
 
-error: cannot find attribute macro `foo` in this scope
+error: cannot find attribute `foo` in this scope
   --> $DIR/custom_attribute.rs:7:7
    |
 LL |     #[foo]
diff --git a/src/test/ui/defaulted-never-note.stderr b/src/test/ui/defaulted-never-note.stderr
index 45174c3..277477a 100644
--- a/src/test/ui/defaulted-never-note.stderr
+++ b/src/test/ui/defaulted-never-note.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied
   --> $DIR/defaulted-never-note.rs:26:5
    |
+LL | fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
+   | ----------------------------------------------- required by `foo`
+...
 LL |     foo(_x);
    |     ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
    |
    = note: the trait is implemented for `()`. Possibly this error has been caused by changes to Rust's type-inference algorithm (see: https://github.com/rust-lang/rust/issues/48950 for more info). Consider whether you meant to use the type `()` here instead.
-note: required by `foo`
-  --> $DIR/defaulted-never-note.rs:21:1
-   |
-LL | fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/deprecation/deprecation-in-future.rs b/src/test/ui/deprecation/deprecation-in-future.rs
index c4f9fdc..464ddcc 100644
--- a/src/test/ui/deprecation/deprecation-in-future.rs
+++ b/src/test/ui/deprecation/deprecation-in-future.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 #![deny(deprecated_in_future)]
 
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
index b9e175e..038de80 100644
--- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
@@ -5,7 +5,7 @@
    | ------------------ method `clone` not found for this
 ...
 LL |     Bar::<NotClone> { x: 1 }.clone();
-   |                              ^^^^^
+   |                              ^^^^^ method not found in `Bar<NotClone>`
    |
    = note: the method `clone` exists but the following trait bounds were not satisfied:
            `Bar<NotClone> : std::clone::Clone`
diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr
index e6060c2..46b6a0d 100644
--- a/src/test/ui/derives/deriving-copyclone.stderr
+++ b/src/test/ui/derives/deriving-copyclone.stderr
@@ -1,41 +1,35 @@
 error[E0277]: the trait bound `C: std::marker::Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:31:5
    |
+LL | fn is_copy<T: Copy>(_: T) {}
+   | ------------------------- required by `is_copy`
+...
 LL |     is_copy(B { a: 1, b: C });
    |     ^^^^^^^ the trait `std::marker::Copy` is not implemented for `C`
    |
    = note: required because of the requirements on the impl of `std::marker::Copy` for `B<C>`
-note: required by `is_copy`
-  --> $DIR/deriving-copyclone.rs:18:1
-   |
-LL | fn is_copy<T: Copy>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `C: std::clone::Clone` is not satisfied
   --> $DIR/deriving-copyclone.rs:32:5
    |
+LL | fn is_clone<T: Clone>(_: T) {}
+   | --------------------------- required by `is_clone`
+...
 LL |     is_clone(B { a: 1, b: C });
    |     ^^^^^^^^ the trait `std::clone::Clone` is not implemented for `C`
    |
    = note: required because of the requirements on the impl of `std::clone::Clone` for `B<C>`
-note: required by `is_clone`
-  --> $DIR/deriving-copyclone.rs:19:1
-   |
-LL | fn is_clone<T: Clone>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `D: std::marker::Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:35:5
    |
+LL | fn is_copy<T: Copy>(_: T) {}
+   | ------------------------- required by `is_copy`
+...
 LL |     is_copy(B { a: 1, b: D });
    |     ^^^^^^^ the trait `std::marker::Copy` is not implemented for `D`
    |
    = note: required because of the requirements on the impl of `std::marker::Copy` for `B<D>`
-note: required by `is_copy`
-  --> $DIR/deriving-copyclone.rs:18:1
-   |
-LL | fn is_copy<T: Copy>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index cfb1da0..ea2017f 100644
--- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `i8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:24:5
    |
+LL |     fn bar(&self){}
+   |     ------------- required by `Foo::bar`
+...
 LL |     Foo::<i32>::bar(&1i8);
    |     ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `i8`
    |
@@ -10,15 +13,13 @@
              <i8 as Foo<u32>>
              <i8 as Foo<u64>>
              <i8 as Foo<u8>>
-note: required by `Foo::bar`
-  --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
-   |
-LL |     fn bar(&self){}
-   |     ^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:25:5
    |
+LL |     fn bar(&self){}
+   |     ------------- required by `Foo::bar`
+...
 LL |     Foo::<i32>::bar(&1u8);
    |     ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `u8`
    |
@@ -27,15 +28,13 @@
              <u8 as Foo<u16>>
              <u8 as Foo<u32>>
              <u8 as Foo<u64>>
-note: required by `Foo::bar`
-  --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
-   |
-LL |     fn bar(&self){}
-   |     ^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:26:5
    |
+LL |     fn bar(&self){}
+   |     ------------- required by `Foo::bar`
+...
 LL |     Foo::<i32>::bar(&true);
    |     ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `bool`
    |
@@ -45,11 +44,6 @@
              <bool as Foo<u16>>
              <bool as Foo<u32>>
            and 2 others
-note: required by `Foo::bar`
-  --> $DIR/issue-39802-show-5-trait-impls.rs:2:5
-   |
-LL |     fn bar(&self){}
-   |     ^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index 87e48cd..5b38404 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -61,8 +61,9 @@
    |
 LL | impl dyn X {
    |      ^^^^^ the trait `X` cannot be made into an object
-   |
-   = note: method `xxx` has no receiver
+...
+LL |     fn xxx() { ### }
+   |        --- associated function `xxx` has no `self` parameter
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs
index 63eec50..6902779 100644
--- a/src/test/ui/did_you_mean/issue-40396.rs
+++ b/src/test/ui/did_you_mean/issue-40396.rs
@@ -1,27 +1,16 @@
 fn foo() {
     (0..13).collect<Vec<i32>>();
     //~^ ERROR chained comparison
-    //~| ERROR expected value, found struct `Vec`
-    //~| ERROR expected value, found builtin type `i32`
-    //~| ERROR attempted to take value of method `collect`
 }
 
 fn bar() {
     Vec<i32>::new();
     //~^ ERROR chained comparison
-    //~| ERROR expected value, found struct `Vec`
-    //~| ERROR expected value, found builtin type `i32`
-    //~| ERROR cannot find function `new` in the crate root
 }
 
 fn qux() {
     (0..13).collect<Vec<i32>();
     //~^ ERROR chained comparison
-    //~| ERROR chained comparison
-    //~| ERROR expected value, found struct `Vec`
-    //~| ERROR expected value, found builtin type `i32`
-    //~| ERROR attempted to take value of method `collect`
-    //~| ERROR mismatched types
 }
 
 fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr
index fe517ee..7a08fda 100644
--- a/src/test/ui/did_you_mean/issue-40396.stderr
+++ b/src/test/ui/did_you_mean/issue-40396.stderr
@@ -8,7 +8,7 @@
    = help: or use `(...)` if you meant to specify fn arguments
 
 error: chained comparison operators require parentheses
-  --> $DIR/issue-40396.rs:10:8
+  --> $DIR/issue-40396.rs:7:8
    |
 LL |     Vec<i32>::new();
    |        ^^^^^^^
@@ -17,7 +17,7 @@
    = help: or use `(...)` if you meant to specify fn arguments
 
 error: chained comparison operators require parentheses
-  --> $DIR/issue-40396.rs:18:20
+  --> $DIR/issue-40396.rs:12:20
    |
 LL |     (0..13).collect<Vec<i32>();
    |                    ^^^^^^^^
@@ -25,79 +25,5 @@
    = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
    = help: or use `(...)` if you meant to specify fn arguments
 
-error: chained comparison operators require parentheses
-  --> $DIR/issue-40396.rs:18:24
-   |
-LL |     (0..13).collect<Vec<i32>();
-   |                        ^^^^^^
-   |
-   = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
-   = help: or use `(...)` if you meant to specify fn arguments
+error: aborting due to 3 previous errors
 
-error[E0423]: expected value, found struct `Vec`
-  --> $DIR/issue-40396.rs:2:21
-   |
-LL |     (0..13).collect<Vec<i32>>();
-   |                     ^^^ did you mean `Vec { /* fields */ }`?
-
-error[E0423]: expected value, found builtin type `i32`
-  --> $DIR/issue-40396.rs:2:25
-   |
-LL |     (0..13).collect<Vec<i32>>();
-   |                         ^^^ not a value
-
-error[E0423]: expected value, found struct `Vec`
-  --> $DIR/issue-40396.rs:10:5
-   |
-LL |     Vec<i32>::new();
-   |     ^^^ did you mean `Vec { /* fields */ }`?
-
-error[E0423]: expected value, found builtin type `i32`
-  --> $DIR/issue-40396.rs:10:9
-   |
-LL |     Vec<i32>::new();
-   |         ^^^ not a value
-
-error[E0425]: cannot find function `new` in the crate root
-  --> $DIR/issue-40396.rs:10:15
-   |
-LL |     Vec<i32>::new();
-   |               ^^^ not found in the crate root
-
-error[E0423]: expected value, found struct `Vec`
-  --> $DIR/issue-40396.rs:18:21
-   |
-LL |     (0..13).collect<Vec<i32>();
-   |                     ^^^ did you mean `Vec { /* fields */ }`?
-
-error[E0423]: expected value, found builtin type `i32`
-  --> $DIR/issue-40396.rs:18:25
-   |
-LL |     (0..13).collect<Vec<i32>();
-   |                         ^^^ not a value
-
-error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>`
-  --> $DIR/issue-40396.rs:2:13
-   |
-LL |     (0..13).collect<Vec<i32>>();
-   |             ^^^^^^^ help: use parentheses to call the method: `collect()`
-
-error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>`
-  --> $DIR/issue-40396.rs:18:13
-   |
-LL |     (0..13).collect<Vec<i32>();
-   |             ^^^^^^^ help: use parentheses to call the method: `collect()`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-40396.rs:18:29
-   |
-LL |     (0..13).collect<Vec<i32>();
-   |                             ^^ expected bool, found ()
-   |
-   = note: expected type `bool`
-              found type `()`
-
-error: aborting due to 14 previous errors
-
-Some errors have detailed explanations: E0308, E0423, E0425, E0615.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr
index a646d98..745d90a 100644
--- a/src/test/ui/did_you_mean/recursion_limit.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit.stderr
@@ -1,6 +1,9 @@
 error[E0275]: overflow evaluating the requirement `J: std::marker::Send`
   --> $DIR/recursion_limit.rs:34:5
    |
+LL | fn is_send<T:Send>() { }
+   | -------------------- required by `is_send`
+...
 LL |     is_send::<A>();
    |     ^^^^^^^^^^^^
    |
@@ -14,11 +17,6 @@
    = note: required because it appears within the type `C`
    = note: required because it appears within the type `B`
    = note: required because it appears within the type `A`
-note: required by `is_send`
-  --> $DIR/recursion_limit.rs:31:1
-   |
-LL | fn is_send<T:Send>() { }
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/drop/dropck_legal_cycles.rs b/src/test/ui/drop/dropck_legal_cycles.rs
index a4f4c26..fb13fd7 100644
--- a/src/test/ui/drop/dropck_legal_cycles.rs
+++ b/src/test/ui/drop/dropck_legal_cycles.rs
@@ -143,7 +143,7 @@
     v[0].descend_into_self(&mut c);
     assert!(!c.saw_prev_marked); // <-- different from below, b/c acyclic above
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 1: { v[0] -> v[1], v[1] -> v[0] };
     // does not exercise `v` itself
@@ -158,7 +158,7 @@
     v[0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 2: { v[0] -> v, v[1] -> v }
     let v: V = Named::new("v");
@@ -171,7 +171,7 @@
     v.descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 3: { hk0 -> hv0, hv0 -> hk0, hk1 -> hv1, hv1 -> hk1 };
     // does not exercise `h` itself
@@ -193,7 +193,7 @@
         assert!(c.saw_prev_marked);
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 4: { h -> (hmk0,hmv0,hmk1,hmv1), {hmk0,hmv0,hmk1,hmv1} -> h }
 
@@ -216,7 +216,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 5: { vd[0] -> vd[1], vd[1] -> vd[0] };
     // does not exercise vd itself
@@ -232,7 +232,7 @@
     vd[0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 6: { vd -> (vd0, vd1), {vd0, vd1} -> vd }
     let mut vd: VecDeque<VD> = VecDeque::new();
@@ -247,7 +247,7 @@
     vd[0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 7: { vm -> (vm0, vm1), {vm0, vm1} -> vm }
     let mut vm: HashMap<usize, VM> = HashMap::new();
@@ -262,7 +262,7 @@
     vm[&0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 8: { ll -> (ll0, ll1), {ll0, ll1} -> ll }
     let mut ll: LinkedList<LL> = LinkedList::new();
@@ -282,7 +282,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 9: { bh -> (bh0, bh1), {bh0, bh1} -> bh }
     let mut bh: BinaryHeap<BH> = BinaryHeap::new();
@@ -302,7 +302,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 10: { btm -> (btk0, btv1), {bt0, bt1} -> btm }
     let mut btm: BTreeMap<BTM, BTM> = BTreeMap::new();
@@ -323,7 +323,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 10: { bts -> (bts0, bts1), {bts0, bts1} -> btm }
     let mut bts: BTreeSet<BTS> = BTreeSet::new();
@@ -343,7 +343,7 @@
         // break;
     }
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 11: { rc0 -> (rc1, rc2), rc1 -> (), rc2 -> rc0 }
     let (rc0, rc1, rc2): (RCRC, RCRC, RCRC);
@@ -361,7 +361,7 @@
     rc0.descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // We want to take the previous Rc case and generalize it to Arc.
     //
@@ -395,7 +395,7 @@
     arc0.descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 13: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, rwlocks
     let (arc0, arc1, arc2): (ARCRW, ARCRW, ARCRW);
@@ -413,7 +413,7 @@
     arc0.descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
-    if PRINT { println!(""); }
+    if PRINT { println!(); }
 
     // Cycle 14: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, mutexs
     let (arc0, arc1, arc2): (ARCM, ARCM, ARCM);
diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs
index 79d09d1..91063ed 100644
--- a/src/test/ui/drop/dynamic-drop-async.rs
+++ b/src/test/ui/drop/dynamic-drop-async.rs
@@ -8,6 +8,7 @@
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(slice_patterns)]
+#![allow(unused)]
 
 use std::{
     cell::{Cell, RefCell},
diff --git a/src/test/ui/elided-test.stderr b/src/test/ui/elided-test.stderr
index d22eee4..175bd03 100644
--- a/src/test/ui/elided-test.stderr
+++ b/src/test/ui/elided-test.stderr
@@ -1,6 +1,10 @@
 error[E0601]: `main` function not found in crate `elided_test`
+  --> $DIR/elided-test.rs:5:1
    |
-   = note: consider adding a `main` function to `$DIR/elided-test.rs`
+LL | / #[test]
+LL | | fn main() {
+LL | | }
+   | |_^ consider adding a `main` function to `$DIR/elided-test.rs`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/empty/empty-macro-use.stderr b/src/test/ui/empty/empty-macro-use.stderr
index 1630041..8e3e068 100644
--- a/src/test/ui/empty/empty-macro-use.stderr
+++ b/src/test/ui/empty/empty-macro-use.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `macro_two!` in this scope
+error: cannot find macro `macro_two` in this scope
   --> $DIR/empty-macro-use.rs:7:5
    |
 LL |     macro_two!();
diff --git a/src/test/ui/empty/empty-never-array.rs b/src/test/ui/empty/empty-never-array.rs
index ffd2545..f0ecea4 100644
--- a/src/test/ui/empty/empty-never-array.rs
+++ b/src/test/ui/empty/empty-never-array.rs
@@ -10,7 +10,7 @@
     let Helper::U(u) = Helper::T(t, []);
     //~^ ERROR refutable pattern in local binding: `T(_, _)` not covered
     u
-    //~^ ERROR use of possibly uninitialized variable: `u`
+    //~^ ERROR use of possibly-uninitialized variable: `u`
 }
 
 fn main() {
diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr
index 01ee1c3..7d59d55 100644
--- a/src/test/ui/empty/empty-never-array.stderr
+++ b/src/test/ui/empty/empty-never-array.stderr
@@ -3,6 +3,7 @@
    |
 LL | / enum Helper<T, U> {
 LL | |     T(T, [!; 0]),
+   | |     - not covered
 LL | |     #[allow(dead_code)]
 LL | |     U(U),
 LL | | }
@@ -11,11 +12,11 @@
 LL |       let Helper::U(u) = Helper::T(t, []);
    |           ^^^^^^^^^^^^ pattern `T(_, _)` not covered
 
-error[E0381]: use of possibly uninitialized variable: `u`
+error[E0381]: use of possibly-uninitialized variable: `u`
   --> $DIR/empty-never-array.rs:12:5
    |
 LL |     u
-   |     ^ use of possibly uninitialized `u`
+   |     ^ use of possibly-uninitialized `u`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0008.rs b/src/test/ui/error-codes/E0008.rs
deleted file mode 100644
index c87ef4c..0000000
--- a/src/test/ui/error-codes/E0008.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    match Some("hi".to_string()) {
-        Some(s) if s.len() == 0 => {},
-        //~^ ERROR E0008
-        _ => {},
-    }
-}
diff --git a/src/test/ui/error-codes/E0008.stderr b/src/test/ui/error-codes/E0008.stderr
deleted file mode 100644
index 6b45439..0000000
--- a/src/test/ui/error-codes/E0008.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0008]: cannot bind by-move into a pattern guard
-  --> $DIR/E0008.rs:3:14
-   |
-LL |         Some(s) if s.len() == 0 => {},
-   |              ^ moves value into pattern guard
-   |
-   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr
index 1bc90a9..d04e494 100644
--- a/src/test/ui/error-codes/E0023.stderr
+++ b/src/test/ui/error-codes/E0023.stderr
@@ -1,18 +1,27 @@
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
   --> $DIR/E0023.rs:10:9
    |
+LL |     Apple(String, String),
+   |     --------------------- tuple variant defined here
+...
 LL |         Fruit::Apple(a) => {},
    |         ^^^^^^^^^^^^^^^ expected 2 fields, found 1
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
   --> $DIR/E0023.rs:11:9
    |
+LL |     Apple(String, String),
+   |     --------------------- tuple variant defined here
+...
 LL |         Fruit::Apple(a, b, c) => {},
    |         ^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3
 
 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field
   --> $DIR/E0023.rs:12:9
    |
+LL |     Pear(u32),
+   |     --------- tuple variant defined here
+...
 LL |         Fruit::Pear(1, 2) => {},
    |         ^^^^^^^^^^^^^^^^^ expected 1 field, found 2
 
diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs
index 6a27b07..1943965 100644
--- a/src/test/ui/error-codes/E0033-teach.rs
+++ b/src/test/ui/error-codes/E0033-teach.rs
@@ -1,14 +1,13 @@
 // compile-flags: -Z teach
 
 trait SomeTrait {
-    fn foo();
+    fn foo(); //~ associated function `foo` has no `self` parameter
 }
 
 fn main() {
     let trait_obj: &dyn SomeTrait = SomeTrait;
     //~^ ERROR expected value, found trait `SomeTrait`
     //~| ERROR E0038
-    //~| method `foo` has no receiver
 
     let &invalid = trait_obj;
     //~^ ERROR E0033
diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr
index fb630de..80f3d44 100644
--- a/src/test/ui/error-codes/E0033-teach.stderr
+++ b/src/test/ui/error-codes/E0033-teach.stderr
@@ -7,13 +7,14 @@
 error[E0038]: the trait `SomeTrait` cannot be made into an object
   --> $DIR/E0033-teach.rs:8:20
    |
+LL |     fn foo();
+   |        --- associated function `foo` has no `self` parameter
+...
 LL |     let trait_obj: &dyn SomeTrait = SomeTrait;
    |                    ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
-   |
-   = note: method `foo` has no receiver
 
 error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
-  --> $DIR/E0033-teach.rs:13:9
+  --> $DIR/E0033-teach.rs:12:9
    |
 LL |     let &invalid = trait_obj;
    |         ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs
index 582600e..e5f0530 100644
--- a/src/test/ui/error-codes/E0033.rs
+++ b/src/test/ui/error-codes/E0033.rs
@@ -1,12 +1,11 @@
 trait SomeTrait {
-    fn foo();
+    fn foo(); //~ associated function `foo` has no `self` parameter
 }
 
 fn main() {
     let trait_obj: &dyn SomeTrait = SomeTrait;
     //~^ ERROR expected value, found trait `SomeTrait`
     //~| ERROR E0038
-    //~| method `foo` has no receiver
 
     let &invalid = trait_obj;
     //~^ ERROR E0033
diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr
index fe9f45d..c284379 100644
--- a/src/test/ui/error-codes/E0033.stderr
+++ b/src/test/ui/error-codes/E0033.stderr
@@ -7,13 +7,14 @@
 error[E0038]: the trait `SomeTrait` cannot be made into an object
   --> $DIR/E0033.rs:6:20
    |
+LL |     fn foo();
+   |        --- associated function `foo` has no `self` parameter
+...
 LL |     let trait_obj: &dyn SomeTrait = SomeTrait;
    |                    ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
-   |
-   = note: method `foo` has no receiver
 
 error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
-  --> $DIR/E0033.rs:11:9
+  --> $DIR/E0033.rs:10:9
    |
 LL |     let &invalid = trait_obj;
    |         ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr
index e3d7593..5c4d6d5 100644
--- a/src/test/ui/error-codes/E0038.stderr
+++ b/src/test/ui/error-codes/E0038.stderr
@@ -1,10 +1,11 @@
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/E0038.rs:5:1
    |
+LL |     fn foo(&self) -> Self;
+   |        --- method `foo` references the `Self` type in its parameters or return type
+...
 LL | fn call_foo(x: Box<dyn Trait>) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object
-   |
-   = note: method `foo` references the `Self` type in its arguments or return type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0044.rs b/src/test/ui/error-codes/E0044.rs
index a5265e7..9eee9c3 100644
--- a/src/test/ui/error-codes/E0044.rs
+++ b/src/test/ui/error-codes/E0044.rs
@@ -1,7 +1,7 @@
 extern {
     fn sqrt<T>(f: T) -> T;
     //~^ ERROR foreign items may not have type parameters [E0044]
-    //~| HELP use specialization instead of type parameters by replacing them with concrete types
+    //~| HELP replace the type parameters with concrete types
     //~| NOTE can't have type parameters
 }
 
diff --git a/src/test/ui/error-codes/E0044.stderr b/src/test/ui/error-codes/E0044.stderr
index 57c2111..e889c16 100644
--- a/src/test/ui/error-codes/E0044.stderr
+++ b/src/test/ui/error-codes/E0044.stderr
@@ -4,7 +4,7 @@
 LL |     fn sqrt<T>(f: T) -> T;
    |     ^^^^^^^^^^^^^^^^^^^^^^ can't have type parameters
    |
-   = help: use specialization instead of type parameters by replacing them with concrete types like `u32`
+   = help: replace the type parameters with concrete types like `u32`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0138.stderr b/src/test/ui/error-codes/E0138.stderr
index 745dccf..445053a 100644
--- a/src/test/ui/error-codes/E0138.stderr
+++ b/src/test/ui/error-codes/E0138.stderr
@@ -1,4 +1,4 @@
-error[E0138]: multiple 'start' functions
+error[E0138]: multiple `start` functions
   --> $DIR/E0138.rs:7:1
    |
 LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 }
diff --git a/src/test/ui/error-codes/E0271.stderr b/src/test/ui/error-codes/E0271.stderr
index 16c3ab9..0afcbcc 100644
--- a/src/test/ui/error-codes/E0271.stderr
+++ b/src/test/ui/error-codes/E0271.stderr
@@ -1,16 +1,14 @@
 error[E0271]: type mismatch resolving `<i8 as Trait>::AssociatedType == u32`
   --> $DIR/E0271.rs:10:5
    |
+LL | fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
+   | -------------------------------------------------- required by `foo`
+...
 LL |     foo(3_i8);
    |     ^^^ expected reference, found u32
    |
    = note: expected type `&'static str`
               found type `u32`
-note: required by `foo`
-  --> $DIR/E0271.rs:3:1
-   |
-LL | fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr
index 40991cb..f607a9f 100644
--- a/src/test/ui/error-codes/E0275.stderr
+++ b/src/test/ui/error-codes/E0275.stderr
@@ -1,6 +1,9 @@
 error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
   --> $DIR/E0275.rs:5:1
    |
+LL | trait Foo {}
+   | --------- required by `Foo`
+...
 LL | impl<T> Foo for T where Bar<T>: Foo {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -132,11 +135,6 @@
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<T>>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<T>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<T>`
-note: required by `Foo`
-  --> $DIR/E0275.rs:1:1
-   |
-LL | trait Foo {}
-   | ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0277-2.stderr b/src/test/ui/error-codes/E0277-2.stderr
index a4db1c8..b42849c 100644
--- a/src/test/ui/error-codes/E0277-2.stderr
+++ b/src/test/ui/error-codes/E0277-2.stderr
@@ -1,6 +1,9 @@
 error[E0277]: `*const u8` cannot be sent between threads safely
   --> $DIR/E0277-2.rs:16:5
    |
+LL | fn is_send<T: Send>() { }
+   | --------------------- required by `is_send`
+...
 LL |     is_send::<Foo>();
    |     ^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
    |
@@ -8,11 +11,6 @@
    = note: required because it appears within the type `Baz`
    = note: required because it appears within the type `Bar`
    = note: required because it appears within the type `Foo`
-note: required by `is_send`
-  --> $DIR/E0277-2.rs:13:1
-   |
-LL | fn is_send<T: Send>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr
index e5e416d..352102d 100644
--- a/src/test/ui/error-codes/E0277.stderr
+++ b/src/test/ui/error-codes/E0277.stderr
@@ -13,14 +13,11 @@
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/E0277.rs:17:5
    |
+LL | fn some_func<T: Foo>(foo: T) {
+   | ---------------------------- required by `some_func`
+...
 LL |     some_func(5i32);
    |     ^^^^^^^^^ the trait `Foo` is not implemented for `i32`
-   |
-note: required by `some_func`
-  --> $DIR/E0277.rs:9:1
-   |
-LL | fn some_func<T: Foo>(foo: T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr
index e1f53e5..1d99f99 100644
--- a/src/test/ui/error-codes/E0283.stderr
+++ b/src/test/ui/error-codes/E0283.stderr
@@ -1,14 +1,11 @@
 error[E0283]: type annotations required: cannot resolve `_: Generator`
   --> $DIR/E0283.rs:18:21
    |
+LL |     fn create() -> u32;
+   |     ------------------- required by `Generator::create`
+...
 LL |     let cont: u32 = Generator::create();
    |                     ^^^^^^^^^^^^^^^^^
-   |
-note: required by `Generator::create`
-  --> $DIR/E0283.rs:2:5
-   |
-LL |     fn create() -> u32;
-   |     ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0301.rs b/src/test/ui/error-codes/E0301.rs
deleted file mode 100644
index 3b45180..0000000
--- a/src/test/ui/error-codes/E0301.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    match Some(()) {
-        None => { },
-        option if option.take().is_none() => {}, //~ ERROR E0301
-        Some(_) => { } //~^ ERROR E0596
-    }
-}
diff --git a/src/test/ui/error-codes/E0301.stderr b/src/test/ui/error-codes/E0301.stderr
deleted file mode 100644
index 4f12fd3..0000000
--- a/src/test/ui/error-codes/E0301.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0301]: cannot mutably borrow in a pattern guard
-  --> $DIR/E0301.rs:4:19
-   |
-LL |         option if option.take().is_none() => {},
-   |                   ^^^^^^ borrowed mutably in pattern guard
-   |
-   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
-
-error[E0596]: cannot borrow `option` as mutable, as it is immutable for the pattern guard
-  --> $DIR/E0301.rs:4:19
-   |
-LL |         option if option.take().is_none() => {},
-   |                   ^^^^^^ cannot borrow as mutable
-   |
-   = note: variables bound in patterns are immutable until the end of the pattern guard
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0301, E0596.
-For more information about an error, try `rustc --explain E0301`.
diff --git a/src/test/ui/error-codes/E0302.rs b/src/test/ui/error-codes/E0302.rs
deleted file mode 100644
index 69f5953..0000000
--- a/src/test/ui/error-codes/E0302.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-fn main() {
-    match Some(()) {
-        None => { },
-        option if { option = None; false } => { }, //~ ERROR E0302
-        //~^ ERROR cannot assign to `option`, as it is immutable for the pattern guard
-        Some(_) => { }
-    }
-}
diff --git a/src/test/ui/error-codes/E0302.stderr b/src/test/ui/error-codes/E0302.stderr
deleted file mode 100644
index a077fca..0000000
--- a/src/test/ui/error-codes/E0302.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0302]: cannot assign in a pattern guard
-  --> $DIR/E0302.rs:4:21
-   |
-LL |         option if { option = None; false } => { },
-   |                     ^^^^^^^^^^^^^ assignment in pattern guard
-
-error[E0594]: cannot assign to `option`, as it is immutable for the pattern guard
-  --> $DIR/E0302.rs:4:21
-   |
-LL |         option if { option = None; false } => { },
-   |                     ^^^^^^^^^^^^^ cannot assign
-   |
-   = note: variables bound in patterns are immutable until the end of the pattern guard
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0302`.
diff --git a/src/test/ui/error-codes/E0601.rs b/src/test/ui/error-codes/E0601.rs
index 47feb7f..4380dde 100644
--- a/src/test/ui/error-codes/E0601.rs
+++ b/src/test/ui/error-codes/E0601.rs
@@ -1 +1 @@
-// Test for main function not found.
+//~ ERROR `main` function not found
diff --git a/src/test/ui/error-codes/E0601.stderr b/src/test/ui/error-codes/E0601.stderr
index cbc20db..a687f57 100644
--- a/src/test/ui/error-codes/E0601.stderr
+++ b/src/test/ui/error-codes/E0601.stderr
@@ -1,6 +1,8 @@
 error[E0601]: `main` function not found in crate `E0601`
+  --> $DIR/E0601.rs:1:37
    |
-   = note: consider adding a `main` function to `$DIR/E0601.rs`
+LL |
+   |                                     ^ consider adding a `main` function to `$DIR/E0601.rs`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index 8808e95..73571a3 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -24,7 +24,7 @@
   --> $DIR/error-festival.rs:16:7
    |
 LL |     x.z();
-   |       ^
+   |       ^ method not found in `&str`
 
 error[E0600]: cannot apply unary operator `!` to type `Question`
   --> $DIR/error-festival.rs:19:5
diff --git a/src/test/ui/error-should-say-copy-not-pod.stderr b/src/test/ui/error-should-say-copy-not-pod.stderr
index 7143f8c..78d54c3 100644
--- a/src/test/ui/error-should-say-copy-not-pod.stderr
+++ b/src/test/ui/error-should-say-copy-not-pod.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
   --> $DIR/error-should-say-copy-not-pod.rs:6:5
    |
+LL | fn check_bound<T:Copy>(_: T) {}
+   | ---------------------------- required by `check_bound`
+...
 LL |     check_bound("nocopy".to_string());
    |     ^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
-   |
-note: required by `check_bound`
-  --> $DIR/error-should-say-copy-not-pod.rs:3:1
-   |
-LL | fn check_bound<T:Copy>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs
index 82c64bc..9ab8e13 100644
--- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs
+++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.rs
@@ -6,11 +6,11 @@
 impl<'a,'b> Foo<'a,'b> {
     fn bar(self:
            Foo<'b,'a>
-    //~^ ERROR mismatched method receiver
+    //~^ ERROR mismatched `self` parameter type
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
     //~| lifetime mismatch
-    //~| ERROR mismatched method receiver
+    //~| ERROR mismatched `self` parameter type
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
     //~| lifetime mismatch
diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr
index e6f9ede..4bf2d57 100644
--- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr
+++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr
@@ -1,4 +1,4 @@
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/explicit-self-lifetime-mismatch.rs:8:12
    |
 LL |            Foo<'b,'a>
@@ -17,7 +17,7 @@
 LL | impl<'a,'b> Foo<'a,'b> {
    |      ^^
 
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/explicit-self-lifetime-mismatch.rs:8:12
    |
 LL |            Foo<'b,'a>
diff --git a/src/test/ui/ext-nonexistent.stderr b/src/test/ui/ext-nonexistent.stderr
index 3fbbb49..f3aa83f 100644
--- a/src/test/ui/ext-nonexistent.stderr
+++ b/src/test/ui/ext-nonexistent.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `iamnotanextensionthatexists!` in this scope
+error: cannot find macro `iamnotanextensionthatexists` in this scope
   --> $DIR/ext-nonexistent.rs:2:13
    |
 LL | fn main() { iamnotanextensionthatexists!(""); }
diff --git a/src/test/ui/extenv/issue-55897.rs b/src/test/ui/extenv/issue-55897.rs
index c3975f6..64c4107 100644
--- a/src/test/ui/extenv/issue-55897.rs
+++ b/src/test/ui/extenv/issue-55897.rs
@@ -1,7 +1,7 @@
 use prelude::*; //~ ERROR unresolved import `prelude`
 
 mod unresolved_env {
-    use env;
+    use env; //~ ERROR unresolved import `env`
 
     include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
     //~^ ERROR cannot determine resolution for the macro `env`
diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr
index 9d68131..c57a467 100644
--- a/src/test/ui/extenv/issue-55897.stderr
+++ b/src/test/ui/extenv/issue-55897.stderr
@@ -19,6 +19,12 @@
    |     unresolved import
    |     help: a similar path exists: `std::prelude`
 
+error[E0432]: unresolved import `env`
+  --> $DIR/issue-55897.rs:4:9
+   |
+LL |     use env;
+   |         ^^^ no `env` in the root
+
 error: cannot determine resolution for the macro `env`
   --> $DIR/issue-55897.rs:6:22
    |
@@ -27,6 +33,6 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/extern/extern-types-not-sync-send.stderr b/src/test/ui/extern/extern-types-not-sync-send.stderr
index bc9d96d..0f32d44 100644
--- a/src/test/ui/extern/extern-types-not-sync-send.stderr
+++ b/src/test/ui/extern/extern-types-not-sync-send.stderr
@@ -1,28 +1,24 @@
 error[E0277]: `A` cannot be shared between threads safely
   --> $DIR/extern-types-not-sync-send.rs:13:5
    |
+LL | fn assert_sync<T: ?Sized + Sync>() { }
+   | ---------------------------------- required by `assert_sync`
+...
 LL |     assert_sync::<A>();
    |     ^^^^^^^^^^^^^^^^ `A` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `A`
-note: required by `assert_sync`
-  --> $DIR/extern-types-not-sync-send.rs:9:1
-   |
-LL | fn assert_sync<T: ?Sized + Sync>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `A` cannot be sent between threads safely
   --> $DIR/extern-types-not-sync-send.rs:16:5
    |
+LL | fn assert_send<T: ?Sized + Send>() { }
+   | ---------------------------------- required by `assert_send`
+...
 LL |     assert_send::<A>();
    |     ^^^^^^^^^^^^^^^^ `A` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `A`
-note: required by `assert_send`
-  --> $DIR/extern-types-not-sync-send.rs:10:1
-   |
-LL | fn assert_send<T: ?Sized + Send>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/extern/extern-types-unsized.stderr b/src/test/ui/extern/extern-types-unsized.stderr
index 4e4f555..06527d9 100644
--- a/src/test/ui/extern/extern-types-unsized.stderr
+++ b/src/test/ui/extern/extern-types-unsized.stderr
@@ -1,50 +1,47 @@
 error[E0277]: the size for values of type `A` cannot be known at compilation time
   --> $DIR/extern-types-unsized.rs:22:5
    |
+LL | fn assert_sized<T>() { }
+   | -------------------- required by `assert_sized`
+...
 LL |     assert_sized::<A>();
    |     ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `A`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-note: required by `assert_sized`
-  --> $DIR/extern-types-unsized.rs:19:1
-   |
-LL | fn assert_sized<T>() { }
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
   --> $DIR/extern-types-unsized.rs:25:5
    |
+LL | fn assert_sized<T>() { }
+   | -------------------- required by `assert_sized`
+...
 LL |     assert_sized::<Foo>();
    |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `Foo`, the trait `std::marker::Sized` is not implemented for `A`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: required because it appears within the type `Foo`
-note: required by `assert_sized`
-  --> $DIR/extern-types-unsized.rs:19:1
-   |
-LL | fn assert_sized<T>() { }
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
   --> $DIR/extern-types-unsized.rs:28:5
    |
+LL | fn assert_sized<T>() { }
+   | -------------------- required by `assert_sized`
+...
 LL |     assert_sized::<Bar<A>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `Bar<A>`, the trait `std::marker::Sized` is not implemented for `A`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: required because it appears within the type `Bar<A>`
-note: required by `assert_sized`
-  --> $DIR/extern-types-unsized.rs:19:1
-   |
-LL | fn assert_sized<T>() { }
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
   --> $DIR/extern-types-unsized.rs:31:5
    |
+LL | fn assert_sized<T>() { }
+   | -------------------- required by `assert_sized`
+...
 LL |     assert_sized::<Bar<Bar<A>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
@@ -52,11 +49,6 @@
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: required because it appears within the type `Bar<A>`
    = note: required because it appears within the type `Bar<Bar<A>>`
-note: required by `assert_sized`
-  --> $DIR/extern-types-unsized.rs:19:1
-   |
-LL | fn assert_sized<T>() { }
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/extern/extern-wrong-value-type.stderr b/src/test/ui/extern/extern-wrong-value-type.stderr
index dce33f3..52fcb90 100644
--- a/src/test/ui/extern/extern-wrong-value-type.stderr
+++ b/src/test/ui/extern/extern-wrong-value-type.stderr
@@ -1,16 +1,14 @@
 error[E0277]: expected a `std::ops::Fn<()>` closure, found `extern "C" fn() {f}`
   --> $DIR/extern-wrong-value-type.rs:9:5
    |
+LL | fn is_fn<F>(_: F) where F: Fn() {}
+   | ------------------------------- required by `is_fn`
+...
 LL |     is_fn(f);
    |     ^^^^^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
    |
    = help: the trait `std::ops::Fn<()>` is not implemented for `extern "C" fn() {f}`
    = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }
-note: required by `is_fn`
-  --> $DIR/extern-wrong-value-type.rs:4:1
-   |
-LL | fn is_fn<F>(_: F) where F: Fn() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gate/allow-features-empty.rs b/src/test/ui/feature-gate/allow-features-empty.rs
index 784a1d2..641e4b8 100644
--- a/src/test/ui/feature-gate/allow-features-empty.rs
+++ b/src/test/ui/feature-gate/allow-features-empty.rs
@@ -1,8 +1,6 @@
 // compile-flags: -Z allow_features=
 // Note: This test uses rustc internal flags because they will never stabilize.
 
-#![feature(rustc_diagnostic_macros)] //~ ERROR
-
 #![feature(rustc_const_unstable)] //~ ERROR
 
 #![feature(lang_items)] //~ ERROR
diff --git a/src/test/ui/feature-gate/allow-features-empty.stderr b/src/test/ui/feature-gate/allow-features-empty.stderr
index ab41422..a87d105 100644
--- a/src/test/ui/feature-gate/allow-features-empty.stderr
+++ b/src/test/ui/feature-gate/allow-features-empty.stderr
@@ -1,27 +1,21 @@
-error[E0725]: the feature `rustc_diagnostic_macros` is not in the list of allowed features
-  --> $DIR/allow-features-empty.rs:4:12
-   |
-LL | #![feature(rustc_diagnostic_macros)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
-  --> $DIR/allow-features-empty.rs:6:12
+  --> $DIR/allow-features-empty.rs:4:12
    |
 LL | #![feature(rustc_const_unstable)]
    |            ^^^^^^^^^^^^^^^^^^^^
 
 error[E0725]: the feature `lang_items` is not in the list of allowed features
-  --> $DIR/allow-features-empty.rs:8:12
+  --> $DIR/allow-features-empty.rs:6:12
    |
 LL | #![feature(lang_items)]
    |            ^^^^^^^^^^
 
 error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features
-  --> $DIR/allow-features-empty.rs:10:12
+  --> $DIR/allow-features-empty.rs:8:12
    |
 LL | #![feature(unknown_stdlib_feature)]
    |            ^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0725`.
diff --git a/src/test/ui/feature-gate/allow-features.rs b/src/test/ui/feature-gate/allow-features.rs
index de3439a..de69e48 100644
--- a/src/test/ui/feature-gate/allow-features.rs
+++ b/src/test/ui/feature-gate/allow-features.rs
@@ -1,8 +1,6 @@
-// compile-flags: -Z allow_features=rustc_diagnostic_macros,lang_items
+// compile-flags: -Z allow_features=lang_items
 // Note: This test uses rustc internal flags because they will never stabilize.
 
-#![feature(rustc_diagnostic_macros)]
-
 #![feature(rustc_const_unstable)] //~ ERROR
 
 #![feature(lang_items)]
diff --git a/src/test/ui/feature-gate/allow-features.stderr b/src/test/ui/feature-gate/allow-features.stderr
index 5b39a6f..157dddf 100644
--- a/src/test/ui/feature-gate/allow-features.stderr
+++ b/src/test/ui/feature-gate/allow-features.stderr
@@ -1,11 +1,11 @@
 error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
-  --> $DIR/allow-features.rs:6:12
+  --> $DIR/allow-features.rs:4:12
    |
 LL | #![feature(rustc_const_unstable)]
    |            ^^^^^^^^^^^^^^^^^^^^
 
 error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features
-  --> $DIR/allow-features.rs:10:12
+  --> $DIR/allow-features.rs:8:12
    |
 LL | #![feature(unknown_stdlib_feature)]
    |            ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
index 92844f9..b6c8648 100644
--- a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
+++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
@@ -1,4 +1,4 @@
-//~ ERROR kind="static-nobundle" is feature gated
+//~ ERROR kind="static-nobundle" is unstable
 // Test the behavior of rustc when non-existent library is statically linked
 
 // compile-flags: -l static-nobundle=nonexistent
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
index 059559d..cfff4c3 100644
--- a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
+++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
@@ -1,4 +1,4 @@
-error[E0658]: kind="static-nobundle" is feature gated
+error[E0658]: kind="static-nobundle" is unstable
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/37403
    = help: add `#![feature(static_nobundle)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
index 6d51bb3..68ff95e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
@@ -84,12 +84,12 @@
 #![crate_name = "0900"]
 #![crate_type = "bin"] // cannot pass "0800" here
 
-// For #![crate_id], see issue #43142. (I cannot bear to enshrine current behavior in a test)
+#![crate_id = "10"] //~ WARN use of deprecated attribute
 
 // FIXME(#44232) we should warn that this isn't used.
 #![feature(rust1)]
 
-// For #![no_start], see issue #43144. (I cannot bear to enshrine current behavior in a test)
+#![no_start] //~ WARN use of deprecated attribute
 
 // (cannot easily gating state of crate-level #[no_main]; but non crate-level is below at "0400")
 #![no_builtins]
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
index 864df35..b2a6018 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
@@ -186,6 +186,20 @@
    |
    = help: consider an outer attribute, `#[macro_use]` mod ...
 
+warning: use of deprecated attribute `crate_id`: no longer used.
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:87:1
+   |
+LL | #![crate_id = "10"]
+   | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: `#[warn(deprecated)]` on by default
+
+warning: use of deprecated attribute `no_start`: no longer used.
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:92:1
+   |
+LL | #![no_start]
+   | ^^^^^^^^^^^^ help: remove this attribute
+
 warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:12
    |
diff --git a/src/test/ui/feature-gates/bench.rs b/src/test/ui/feature-gates/bench.rs
new file mode 100644
index 0000000..afe4dc7
--- /dev/null
+++ b/src/test/ui/feature-gates/bench.rs
@@ -0,0 +1,5 @@
+#[bench] //~ ERROR use of unstable library feature 'test'
+         //~| WARN this was previously accepted
+fn bench() {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/bench.stderr b/src/test/ui/feature-gates/bench.stderr
new file mode 100644
index 0000000..b9e24e9
--- /dev/null
+++ b/src/test/ui/feature-gates/bench.stderr
@@ -0,0 +1,12 @@
+error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
+  --> $DIR/bench.rs:1:3
+   |
+LL | #[bench]
+   |   ^^^^^
+   |
+   = note: `#[deny(soft_unstable)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs
index 41c9f79..61da38e 100644
--- a/src/test/ui/feature-gates/feature-gate-abi.rs
+++ b/src/test/ui/feature-gates/feature-gate-abi.rs
@@ -10,7 +10,9 @@
 
 // Functions
 extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
+//~^ ERROR intrinsic must be in
 extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
+//~^ ERROR intrinsic must be in
 extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
 extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
 extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
@@ -22,7 +24,9 @@
 // Methods in trait definition
 trait Tr {
     extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change
+    //~^ ERROR intrinsic must be in
     extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
+    //~^ ERROR intrinsic must be in
     extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
     extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
     extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
@@ -31,8 +35,6 @@
     extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change
     extern "amdgpu-kernel" fn m9(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change
 
-    extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
-    extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
     extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
     extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
     extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
@@ -47,7 +49,9 @@
 // Methods in trait impl
 impl Tr for S {
     extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
+    //~^ ERROR intrinsic must be in
     extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
+    //~^ ERROR intrinsic must be in
     extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
     extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
     extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
@@ -60,7 +64,9 @@
 // Methods in inherent impl
 impl S {
     extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
+    //~^ ERROR intrinsic must be in
     extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
+    //~^ ERROR intrinsic must be in
     extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
     extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
     extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr
index 88e0b86..afda76d 100644
--- a/src/test/ui/feature-gates/feature-gate-abi.stderr
+++ b/src/test/ui/feature-gates/feature-gate-abi.stderr
@@ -7,7 +7,7 @@
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:13:1
+  --> $DIR/feature-gate-abi.rs:14:1
    |
 LL | extern "platform-intrinsic" fn f2() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:14:1
+  --> $DIR/feature-gate-abi.rs:16:1
    |
 LL | extern "vectorcall" fn f3() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:15:1
+  --> $DIR/feature-gate-abi.rs:17:1
    |
 LL | extern "rust-call" fn f4() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
 error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:16:1
+  --> $DIR/feature-gate-abi.rs:18:1
    |
 LL | extern "msp430-interrupt" fn f5() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -42,7 +42,7 @@
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
 
 error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:17:1
+  --> $DIR/feature-gate-abi.rs:19:1
    |
 LL | extern "ptx-kernel" fn f6() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -51,7 +51,7 @@
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
 
 error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:18:1
+  --> $DIR/feature-gate-abi.rs:20:1
    |
 LL | extern "x86-interrupt" fn f7() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:19:1
+  --> $DIR/feature-gate-abi.rs:21:1
    |
 LL | extern "thiscall" fn f8() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,7 +68,7 @@
    = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
 
 error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:20:1
+  --> $DIR/feature-gate-abi.rs:22:1
    |
 LL | extern "amdgpu-kernel" fn f9() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@
    = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:24:5
+  --> $DIR/feature-gate-abi.rs:26:5
    |
 LL |     extern "rust-intrinsic" fn m1();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -85,7 +85,7 @@
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:25:5
+  --> $DIR/feature-gate-abi.rs:28:5
    |
 LL |     extern "platform-intrinsic" fn m2();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -94,7 +94,7 @@
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:26:5
+  --> $DIR/feature-gate-abi.rs:30:5
    |
 LL |     extern "vectorcall" fn m3();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -102,7 +102,7 @@
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:27:5
+  --> $DIR/feature-gate-abi.rs:31:5
    |
 LL |     extern "rust-call" fn m4();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -111,7 +111,7 @@
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
 error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:28:5
+  --> $DIR/feature-gate-abi.rs:32:5
    |
 LL |     extern "msp430-interrupt" fn m5();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -120,7 +120,7 @@
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
 
 error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:29:5
+  --> $DIR/feature-gate-abi.rs:33:5
    |
 LL |     extern "ptx-kernel" fn m6();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -129,7 +129,7 @@
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
 
 error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:30:5
+  --> $DIR/feature-gate-abi.rs:34:5
    |
 LL |     extern "x86-interrupt" fn m7();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -138,7 +138,7 @@
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:31:5
+  --> $DIR/feature-gate-abi.rs:35:5
    |
 LL |     extern "thiscall" fn m8();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -146,7 +146,7 @@
    = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
 
 error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:32:5
+  --> $DIR/feature-gate-abi.rs:36:5
    |
 LL |     extern "amdgpu-kernel" fn m9();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,25 +154,8 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/51575
    = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
 
-error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:34:5
-   |
-LL |     extern "rust-intrinsic" fn dm1() {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(intrinsics)]` to the crate attributes to enable
-
-error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:35:5
-   |
-LL |     extern "platform-intrinsic" fn dm2() {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
-   = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
-
 error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:36:5
+  --> $DIR/feature-gate-abi.rs:38:5
    |
 LL |     extern "vectorcall" fn dm3() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -180,7 +163,7 @@
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:37:5
+  --> $DIR/feature-gate-abi.rs:39:5
    |
 LL |     extern "rust-call" fn dm4() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -189,7 +172,7 @@
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
 error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:38:5
+  --> $DIR/feature-gate-abi.rs:40:5
    |
 LL |     extern "msp430-interrupt" fn dm5() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -198,7 +181,7 @@
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
 
 error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:39:5
+  --> $DIR/feature-gate-abi.rs:41:5
    |
 LL |     extern "ptx-kernel" fn dm6() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -207,7 +190,7 @@
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
 
 error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:40:5
+  --> $DIR/feature-gate-abi.rs:42:5
    |
 LL |     extern "x86-interrupt" fn dm7() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -216,7 +199,7 @@
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:41:5
+  --> $DIR/feature-gate-abi.rs:43:5
    |
 LL |     extern "thiscall" fn dm8() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -224,7 +207,7 @@
    = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
 
 error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:42:5
+  --> $DIR/feature-gate-abi.rs:44:5
    |
 LL |     extern "amdgpu-kernel" fn dm9() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -233,7 +216,7 @@
    = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:49:5
+  --> $DIR/feature-gate-abi.rs:51:5
    |
 LL |     extern "rust-intrinsic" fn m1() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -241,7 +224,7 @@
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:50:5
+  --> $DIR/feature-gate-abi.rs:53:5
    |
 LL |     extern "platform-intrinsic" fn m2() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -250,7 +233,7 @@
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:51:5
+  --> $DIR/feature-gate-abi.rs:55:5
    |
 LL |     extern "vectorcall" fn m3() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -258,7 +241,7 @@
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:52:5
+  --> $DIR/feature-gate-abi.rs:56:5
    |
 LL |     extern "rust-call" fn m4() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -267,7 +250,7 @@
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
 error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:53:5
+  --> $DIR/feature-gate-abi.rs:57:5
    |
 LL |     extern "msp430-interrupt" fn m5() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -276,7 +259,7 @@
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
 
 error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:54:5
+  --> $DIR/feature-gate-abi.rs:58:5
    |
 LL |     extern "ptx-kernel" fn m6() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -285,7 +268,7 @@
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
 
 error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:55:5
+  --> $DIR/feature-gate-abi.rs:59:5
    |
 LL |     extern "x86-interrupt" fn m7() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -294,7 +277,7 @@
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:56:5
+  --> $DIR/feature-gate-abi.rs:60:5
    |
 LL |     extern "thiscall" fn m8() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -302,7 +285,7 @@
    = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
 
 error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:57:5
+  --> $DIR/feature-gate-abi.rs:61:5
    |
 LL |     extern "amdgpu-kernel" fn m9() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -311,7 +294,7 @@
    = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:62:5
+  --> $DIR/feature-gate-abi.rs:66:5
    |
 LL |     extern "rust-intrinsic" fn im1() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -319,7 +302,7 @@
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:63:5
+  --> $DIR/feature-gate-abi.rs:68:5
    |
 LL |     extern "platform-intrinsic" fn im2() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -328,7 +311,7 @@
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:64:5
+  --> $DIR/feature-gate-abi.rs:70:5
    |
 LL |     extern "vectorcall" fn im3() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -336,7 +319,7 @@
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:65:5
+  --> $DIR/feature-gate-abi.rs:71:5
    |
 LL |     extern "rust-call" fn im4() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -345,7 +328,7 @@
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
 error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:66:5
+  --> $DIR/feature-gate-abi.rs:72:5
    |
 LL |     extern "msp430-interrupt" fn im5() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -354,7 +337,7 @@
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
 
 error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:67:5
+  --> $DIR/feature-gate-abi.rs:73:5
    |
 LL |     extern "ptx-kernel" fn im6() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -363,7 +346,7 @@
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
 
 error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:68:5
+  --> $DIR/feature-gate-abi.rs:74:5
    |
 LL |     extern "x86-interrupt" fn im7() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -372,7 +355,7 @@
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:69:5
+  --> $DIR/feature-gate-abi.rs:75:5
    |
 LL |     extern "thiscall" fn im8() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -380,7 +363,7 @@
    = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
 
 error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:70:5
+  --> $DIR/feature-gate-abi.rs:76:5
    |
 LL |     extern "amdgpu-kernel" fn im9() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -389,7 +372,7 @@
    = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:74:11
+  --> $DIR/feature-gate-abi.rs:80:11
    |
 LL | type A1 = extern "rust-intrinsic" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -397,7 +380,7 @@
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:75:11
+  --> $DIR/feature-gate-abi.rs:81:11
    |
 LL | type A2 = extern "platform-intrinsic" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -406,7 +389,7 @@
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:76:11
+  --> $DIR/feature-gate-abi.rs:82:11
    |
 LL | type A3 = extern "vectorcall" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -414,7 +397,7 @@
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:77:11
+  --> $DIR/feature-gate-abi.rs:83:11
    |
 LL | type A4 = extern "rust-call" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^
@@ -423,7 +406,7 @@
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
 error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:78:11
+  --> $DIR/feature-gate-abi.rs:84:11
    |
 LL | type A5 = extern "msp430-interrupt" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -432,7 +415,7 @@
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
 
 error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:79:11
+  --> $DIR/feature-gate-abi.rs:85:11
    |
 LL | type A6 = extern "ptx-kernel" fn ();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -441,7 +424,7 @@
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
 
 error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:80:11
+  --> $DIR/feature-gate-abi.rs:86:11
    |
 LL | type A7 = extern "x86-interrupt" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -450,7 +433,7 @@
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:81:11
+  --> $DIR/feature-gate-abi.rs:87:11
    |
 LL | type A8 = extern "thiscall" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^
@@ -458,7 +441,7 @@
    = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
 
 error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:82:11
+  --> $DIR/feature-gate-abi.rs:88:11
    |
 LL | type A9 = extern "amdgpu-kernel" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -467,7 +450,7 @@
    = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:85:1
+  --> $DIR/feature-gate-abi.rs:91:1
    |
 LL | extern "rust-intrinsic" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -475,7 +458,7 @@
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:86:1
+  --> $DIR/feature-gate-abi.rs:92:1
    |
 LL | extern "platform-intrinsic" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -484,7 +467,7 @@
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:87:1
+  --> $DIR/feature-gate-abi.rs:93:1
    |
 LL | extern "vectorcall" {}
    | ^^^^^^^^^^^^^^^^^^^^^^
@@ -492,7 +475,7 @@
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:88:1
+  --> $DIR/feature-gate-abi.rs:94:1
    |
 LL | extern "rust-call" {}
    | ^^^^^^^^^^^^^^^^^^^^^
@@ -501,7 +484,7 @@
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
 error[E0658]: msp430-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:89:1
+  --> $DIR/feature-gate-abi.rs:95:1
    |
 LL | extern "msp430-interrupt" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -510,7 +493,7 @@
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
 
 error[E0658]: PTX ABIs are experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:90:1
+  --> $DIR/feature-gate-abi.rs:96:1
    |
 LL | extern "ptx-kernel" {}
    | ^^^^^^^^^^^^^^^^^^^^^^
@@ -519,7 +502,7 @@
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
 
 error[E0658]: x86-interrupt ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:91:1
+  --> $DIR/feature-gate-abi.rs:97:1
    |
 LL | extern "x86-interrupt" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -528,7 +511,7 @@
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:92:1
+  --> $DIR/feature-gate-abi.rs:98:1
    |
 LL | extern "thiscall" {}
    | ^^^^^^^^^^^^^^^^^^^^
@@ -536,7 +519,7 @@
    = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
 
 error[E0658]: amdgpu-kernel ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:93:1
+  --> $DIR/feature-gate-abi.rs:99:1
    |
 LL | extern "amdgpu-kernel" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -544,6 +527,54 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/51575
    = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
 
-error: aborting due to 63 previous errors
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/feature-gate-abi.rs:26:32
+   |
+LL |     extern "rust-intrinsic" fn m1();
+   |                                ^^
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/feature-gate-abi.rs:28:36
+   |
+LL |     extern "platform-intrinsic" fn m2();
+   |                                    ^^
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/feature-gate-abi.rs:12:33
+   |
+LL | extern "rust-intrinsic" fn f1() {}
+   |                                 ^^
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/feature-gate-abi.rs:14:37
+   |
+LL | extern "platform-intrinsic" fn f2() {}
+   |                                     ^^
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/feature-gate-abi.rs:51:37
+   |
+LL |     extern "rust-intrinsic" fn m1() {}
+   |                                     ^^
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/feature-gate-abi.rs:53:41
+   |
+LL |     extern "platform-intrinsic" fn m2() {}
+   |                                         ^^
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/feature-gate-abi.rs:66:38
+   |
+LL |     extern "rust-intrinsic" fn im1() {}
+   |                                      ^^
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/feature-gate-abi.rs:68:42
+   |
+LL |     extern "platform-intrinsic" fn im2() {}
+   |                                          ^^
+
+error: aborting due to 69 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
index d34936b..936cab2 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
@@ -1,18 +1,18 @@
 // Check that literals in attributes parse just fine.
 
-#[fake_attr] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(100)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr("hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(name = "hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute macro `fake_attr` in th
-#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute macro `fake_attr` in this scop
-#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute macro `fake_attr` in
-#[fake_attr(true)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(b"hi")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_doc(r"doc")] //~ ERROR cannot find attribute macro `fake_doc` in this scope
+#[fake_attr] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(100)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr("hello")] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(name = "hello")] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute `fake_attr` in th
+#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute `fake_attr` in this scop
+#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute `fake_attr` in
+#[fake_attr(true)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(b"hi")] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_doc(r"doc")] //~ ERROR cannot find attribute `fake_doc` in this scope
 struct Q {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
index efdc2d1..b7c45ec 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
@@ -1,76 +1,76 @@
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:3:3
    |
 LL | #[fake_attr]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:4:3
    |
 LL | #[fake_attr(100)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:5:3
    |
 LL | #[fake_attr(1, 2, 3)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:6:3
    |
 LL | #[fake_attr("hello")]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:7:3
    |
 LL | #[fake_attr(name = "hello")]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:8:3
    |
 LL | #[fake_attr(1, "hi", key = 12, true, false)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:9:3
    |
 LL | #[fake_attr(key = "hello", val = 10)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:10:3
    |
 LL | #[fake_attr(key("hello"), val(10))]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:11:3
    |
 LL | #[fake_attr(enabled = true, disabled = false)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:12:3
    |
 LL | #[fake_attr(true)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:13:3
    |
 LL | #[fake_attr(pi = 3.14159)]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:14:3
    |
 LL | #[fake_attr(b"hi")]
    |   ^^^^^^^^^
 
-error: cannot find attribute macro `fake_doc` in this scope
+error: cannot find attribute `fake_doc` in this scope
   --> $DIR/feature-gate-custom_attribute.rs:15:3
    |
 LL | #[fake_doc(r"doc")]
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
index 8fe11cb..e4c8014 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
@@ -4,54 +4,54 @@
 // gate-test-custom_attribute
 
 struct StLt<#[lt_struct] 'a>(&'a u32);
-//~^ ERROR the attribute `lt_struct` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `lt_struct` in this scope
 struct StTy<#[ty_struct] I>(I);
-//~^ ERROR the attribute `ty_struct` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `ty_struct` in this scope
 
 enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
-//~^ ERROR the attribute `lt_enum` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `lt_enum` in this scope
 enum EnTy<#[ty_enum] J> { A(J), B }
-//~^ ERROR the attribute `ty_enum` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `ty_enum` in this scope
 
 trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
-//~^ ERROR the attribute `lt_trait` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `lt_trait` in this scope
 trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
-//~^ ERROR the attribute `ty_trait` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `ty_trait` in this scope
 
 type TyLt<#[lt_type] 'd> = &'d u32;
-//~^ ERROR the attribute `lt_type` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `lt_type` in this scope
 type TyTy<#[ty_type] L> = (L, );
-//~^ ERROR the attribute `ty_type` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `ty_type` in this scope
 
 impl<#[lt_inherent] 'e> StLt<'e> { }
-//~^ ERROR the attribute `lt_inherent` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `lt_inherent` in this scope
 impl<#[ty_inherent] M> StTy<M> { }
-//~^ ERROR the attribute `ty_inherent` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `ty_inherent` in this scope
 
 impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
-    //~^ ERROR the attribute `lt_impl_for` is currently unknown to the compiler
+    //~^ ERROR cannot find attribute `lt_impl_for` in this scope
     fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } }
 }
 impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
-    //~^ ERROR the attribute `ty_impl_for` is currently unknown to the compiler
+    //~^ ERROR cannot find attribute `ty_impl_for` in this scope
     fn foo(&self, _: N) { }
 }
 
 fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
-//~^ ERROR the attribute `lt_fn` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `lt_fn` in this scope
 fn f_ty<#[ty_fn] O>(_: O) { }
-//~^ ERROR the attribute `ty_fn` is currently unknown to the compiler
+//~^ ERROR cannot find attribute `ty_fn` in this scope
 
 impl<I> StTy<I> {
     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
-    //~^ ERROR the attribute `lt_meth` is currently unknown to the compiler
+    //~^ ERROR cannot find attribute `lt_meth` in this scope
     fn m_ty<#[ty_meth] P>(_: P) { }
-    //~^ ERROR the attribute `ty_meth` is currently unknown to the compiler
+    //~^ ERROR cannot find attribute `ty_meth` in this scope
 }
 
 fn hof_lt<Q>(_: Q)
     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
-    //~^ ERROR the attribute `lt_hof` is currently unknown to the compiler
+    //~^ ERROR cannot find attribute `lt_hof` in this scope
 {
 }
 
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
index 15e0c41..bc89cad 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
@@ -1,156 +1,104 @@
-error[E0658]: the attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:6:13
-   |
-LL | struct StLt<#[lt_struct] 'a>(&'a u32);
-   |             ^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:8:13
-   |
-LL | struct StTy<#[ty_struct] I>(I);
-   |             ^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:11:11
-   |
-LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
-   |           ^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:13:11
-   |
-LL | enum EnTy<#[ty_enum] J> { A(J), B }
-   |           ^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:16:12
-   |
-LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
-   |            ^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:18:12
-   |
-LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
-   |            ^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:21:11
-   |
-LL | type TyLt<#[lt_type] 'd> = &'d u32;
-   |           ^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:23:11
-   |
-LL | type TyTy<#[ty_type] L> = (L, );
-   |           ^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:26:6
-   |
-LL | impl<#[lt_inherent] 'e> StLt<'e> { }
-   |      ^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:28:6
-   |
-LL | impl<#[ty_inherent] M> StTy<M> { }
-   |      ^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:31:6
-   |
-LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
-   |      ^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:35:6
-   |
-LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
-   |      ^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:40:9
-   |
-LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
-   |         ^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:42:9
-   |
-LL | fn f_ty<#[ty_fn] O>(_: O) { }
-   |         ^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:46:13
-   |
-LL |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
-   |             ^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:48:13
-   |
-LL |     fn m_ty<#[ty_meth] P>(_: P) { }
-   |             ^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/feature-gate-custom_attribute2.rs:53:19
+error: cannot find attribute `lt_hof` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:53:21
    |
 LL |     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
-   |                   ^^^^^^^^^
+   |                     ^^^^^^
+
+error: cannot find attribute `ty_meth` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:48:15
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
+LL |     fn m_ty<#[ty_meth] P>(_: P) { }
+   |               ^^^^^^^
+
+error: cannot find attribute `lt_meth` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:46:15
+   |
+LL |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
+   |               ^^^^^^^
+
+error: cannot find attribute `ty_fn` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:42:11
+   |
+LL | fn f_ty<#[ty_fn] O>(_: O) { }
+   |           ^^^^^
+
+error: cannot find attribute `lt_fn` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:40:11
+   |
+LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
+   |           ^^^^^
+
+error: cannot find attribute `ty_impl_for` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:35:8
+   |
+LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
+   |        ^^^^^^^^^^^
+
+error: cannot find attribute `lt_impl_for` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:31:8
+   |
+LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
+   |        ^^^^^^^^^^^
+
+error: cannot find attribute `ty_inherent` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:28:8
+   |
+LL | impl<#[ty_inherent] M> StTy<M> { }
+   |        ^^^^^^^^^^^
+
+error: cannot find attribute `lt_inherent` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:26:8
+   |
+LL | impl<#[lt_inherent] 'e> StLt<'e> { }
+   |        ^^^^^^^^^^^
+
+error: cannot find attribute `ty_type` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:23:13
+   |
+LL | type TyTy<#[ty_type] L> = (L, );
+   |             ^^^^^^^
+
+error: cannot find attribute `lt_type` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:21:13
+   |
+LL | type TyLt<#[lt_type] 'd> = &'d u32;
+   |             ^^^^^^^
+
+error: cannot find attribute `ty_trait` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:18:14
+   |
+LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
+   |              ^^^^^^^^
+
+error: cannot find attribute `lt_trait` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:16:14
+   |
+LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
+   |              ^^^^^^^^
+
+error: cannot find attribute `ty_enum` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:13:13
+   |
+LL | enum EnTy<#[ty_enum] J> { A(J), B }
+   |             ^^^^^^^
+
+error: cannot find attribute `lt_enum` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:11:13
+   |
+LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
+   |             ^^^^^^^
+
+error: cannot find attribute `ty_struct` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:8:15
+   |
+LL | struct StTy<#[ty_struct] I>(I);
+   |               ^^^^^^^^^
+
+error: cannot find attribute `lt_struct` in this scope
+  --> $DIR/feature-gate-custom_attribute2.rs:6:15
+   |
+LL | struct StLt<#[lt_struct] 'a>(&'a u32);
+   |               ^^^^^^^^^
 
 error: aborting due to 17 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-doc_alias.rs b/src/test/ui/feature-gates/feature-gate-doc_alias.rs
index adb6fc2..c957221 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_alias.rs
+++ b/src/test/ui/feature-gates/feature-gate-doc_alias.rs
@@ -1,4 +1,4 @@
-#[doc(alias = "foo")] //~ ERROR: `#[doc(alias = "...")]` is experimental
+#[doc(alias = "foo")] //~ ERROR: `#[doc(alias)]` is experimental
 pub struct Foo;
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_alias.stderr b/src/test/ui/feature-gates/feature-gate-doc_alias.stderr
index dddaa45..540b1f5 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_alias.stderr
+++ b/src/test/ui/feature-gates/feature-gate-doc_alias.stderr
@@ -1,4 +1,4 @@
-error[E0658]: `#[doc(alias = "...")]` is experimental
+error[E0658]: `#[doc(alias)]` is experimental
   --> $DIR/feature-gate-doc_alias.rs:1:1
    |
 LL | #[doc(alias = "foo")]
diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg.rs b/src/test/ui/feature-gates/feature-gate-doc_cfg.rs
index bb3846e..b12b8a1 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_cfg.rs
+++ b/src/test/ui/feature-gates/feature-gate-doc_cfg.rs
@@ -1,2 +1,2 @@
-#[doc(cfg(unix))] //~ ERROR: `#[doc(cfg(...))]` is experimental
+#[doc(cfg(unix))] //~ ERROR: `#[doc(cfg)]` is experimental
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr b/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr
index 7b0a231..eaa908d 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr
+++ b/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr
@@ -1,4 +1,4 @@
-error[E0658]: `#[doc(cfg(...))]` is experimental
+error[E0658]: `#[doc(cfg)]` is experimental
   --> $DIR/feature-gate-doc_cfg.rs:1:1
    |
 LL | #[doc(cfg(unix))]
diff --git a/src/test/ui/feature-gates/feature-gate-doc_keyword.rs b/src/test/ui/feature-gates/feature-gate-doc_keyword.rs
index 6cdcfa6..4bb9a40 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_keyword.rs
+++ b/src/test/ui/feature-gates/feature-gate-doc_keyword.rs
@@ -1,4 +1,4 @@
-#[doc(keyword = "match")] //~ ERROR: `#[doc(keyword = "...")]` is experimental
+#[doc(keyword = "match")] //~ ERROR: `#[doc(keyword)]` is experimental
 /// wonderful
 mod foo{}
 
diff --git a/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr b/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr
index abde0be..15a41d9 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr
+++ b/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr
@@ -1,4 +1,4 @@
-error[E0658]: `#[doc(keyword = "...")]` is experimental
+error[E0658]: `#[doc(keyword)]` is experimental
   --> $DIR/feature-gate-doc_keyword.rs:1:1
    |
 LL | #[doc(keyword = "match")]
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.rs b/src/test/ui/feature-gates/feature-gate-external_doc.rs
index dec3fa1..9d68d3e 100644
--- a/src/test/ui/feature-gates/feature-gate-external_doc.rs
+++ b/src/test/ui/feature-gates/feature-gate-external_doc.rs
@@ -1,2 +1,2 @@
-#[doc(include="asdf.md")] //~ ERROR: `#[doc(include = "...")]` is experimental
+#[doc(include="asdf.md")] //~ ERROR: `#[doc(include)]` is experimental
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.stderr b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
index a5a8743..683c0ad 100644
--- a/src/test/ui/feature-gates/feature-gate-external_doc.stderr
+++ b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
@@ -1,4 +1,4 @@
-error[E0658]: `#[doc(include = "...")]` is experimental
+error[E0658]: `#[doc(include)]` is experimental
   --> $DIR/feature-gate-external_doc.rs:1:1
    |
 LL | #[doc(include="asdf.md")]
diff --git a/src/test/ui/feature-gates/feature-gate-intrinsics.rs b/src/test/ui/feature-gates/feature-gate-intrinsics.rs
index d1da943..e0dc3cc 100644
--- a/src/test/ui/feature-gates/feature-gate-intrinsics.rs
+++ b/src/test/ui/feature-gates/feature-gate-intrinsics.rs
@@ -3,5 +3,6 @@
 }
 
 extern "rust-intrinsic" fn baz() {} //~ ERROR intrinsics are subject to change
+//~^ ERROR intrinsic must be in
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-intrinsics.stderr b/src/test/ui/feature-gates/feature-gate-intrinsics.stderr
index 09843f0..101a10e 100644
--- a/src/test/ui/feature-gates/feature-gate-intrinsics.stderr
+++ b/src/test/ui/feature-gates/feature-gate-intrinsics.stderr
@@ -22,7 +22,13 @@
 LL |     fn bar();
    |     ^^^^^^^^^ unrecognized intrinsic
 
-error: aborting due to 3 previous errors
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/feature-gate-intrinsics.rs:5:34
+   |
+LL | extern "rust-intrinsic" fn baz() {}
+   |                                  ^^
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0093, E0658.
 For more information about an error, try `rustc --explain E0093`.
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.rs b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
index 078ecc5..359ed83 100644
--- a/src/test/ui/feature-gates/feature-gate-is_sorted.rs
+++ b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
@@ -1,11 +1,11 @@
 fn main() {
-    // Assert `Iterator` methods are feature gated
+    // Assert `Iterator` methods are unstable
     assert!([1, 2, 2, 9].iter().is_sorted());
     //~^ ERROR: use of unstable library feature 'is_sorted': new API
     assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
     //~^ ERROR: use of unstable library feature 'is_sorted': new API
 
-    // Assert `[T]` methods are feature gated
+    // Assert `[T]` methods are unstable
     assert!([1, 2, 2, 9].is_sorted());
     //~^ ERROR: use of unstable library feature 'is_sorted': new API
     assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.rs b/src/test/ui/feature-gates/feature-gate-link_cfg.rs
index 1905346..27ec2e9 100644
--- a/src/test/ui/feature-gates/feature-gate-link_cfg.rs
+++ b/src/test/ui/feature-gates/feature-gate-link_cfg.rs
@@ -1,5 +1,5 @@
 #[link(name = "foo", cfg(foo))]
-//~^ ERROR: is feature gated
+//~^ ERROR: is unstable
 extern {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
index 58aa4ed..f6c5061 100644
--- a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
+++ b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
@@ -1,4 +1,4 @@
-error[E0658]: is feature gated
+error[E0658]: is unstable
   --> $DIR/feature-gate-link_cfg.rs:1:1
    |
 LL | #[link(name = "foo", cfg(foo))]
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
index 4044fd2..c985298 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
@@ -19,5 +19,5 @@
 //~^ ERROR the `#[rustc_dummy]` attribute is just used for rustc unit tests
 #[rustc_unknown]
 //~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
-//~| ERROR cannot find attribute macro `rustc_unknown` in this scope
+//~| ERROR cannot find attribute `rustc_unknown` in this scope
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
index c106302..d6fdab2 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
@@ -37,7 +37,7 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-error: cannot find attribute macro `rustc_unknown` in this scope
+error: cannot find attribute `rustc_unknown` in this scope
   --> $DIR/feature-gate-rustc-attrs.rs:20:3
    |
 LL | #[rustc_unknown]
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs
deleted file mode 100644
index 63c2c31..0000000
--- a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Test that diagnostic macros are gated by `rustc_diagnostic_macros` feature
-// gate
-
-__register_diagnostic!(E0001);
-//~^ ERROR cannot find macro `__register_diagnostic!` in this scope
-
-fn main() {
-    __diagnostic_used!(E0001);
-    //~^ ERROR cannot find macro `__diagnostic_used!` in this scope
-}
-
-__build_diagnostic_array!(DIAGNOSTICS);
-//~^ ERROR cannot find macro `__build_diagnostic_array!` in this scope
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr
deleted file mode 100644
index 676b8b9..0000000
--- a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: cannot find macro `__build_diagnostic_array!` in this scope
-  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:12:1
-   |
-LL | __build_diagnostic_array!(DIAGNOSTICS);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: cannot find macro `__diagnostic_used!` in this scope
-  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:8:5
-   |
-LL |     __diagnostic_used!(E0001);
-   |     ^^^^^^^^^^^^^^^^^
-
-error: cannot find macro `__register_diagnostic!` in this scope
-  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:4:1
-   |
-LL | __register_diagnostic!(E0001);
-   | ^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.rs b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
index 1ce6c54..644b1f9 100644
--- a/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
@@ -1,5 +1,5 @@
 #[link(name="foo", kind="static-nobundle")]
-//~^ ERROR: kind="static-nobundle" is feature gated
+//~^ ERROR: kind="static-nobundle" is unstable
 extern {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
index f2e29cf..cc0d426 100644
--- a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
@@ -1,4 +1,4 @@
-error[E0658]: kind="static-nobundle" is feature gated
+error[E0658]: kind="static-nobundle" is unstable
   --> $DIR/feature-gate-static-nobundle.rs:1:1
    |
 LL | #[link(name="foo", kind="static-nobundle")]
diff --git a/src/test/ui/feature-gates/feature-gate-type_ascription.rs b/src/test/ui/feature-gates/feature-gate-type_ascription.rs
index e42e340..7a59715 100644
--- a/src/test/ui/feature-gates/feature-gate-type_ascription.rs
+++ b/src/test/ui/feature-gates/feature-gate-type_ascription.rs
@@ -1,4 +1,4 @@
-// Type ascription is feature gated
+// Type ascription is unstable
 
 fn main() {
     let a = 10: u8; //~ ERROR type ascription is experimental
diff --git a/src/test/ui/fmt/send-sync.stderr b/src/test/ui/fmt/send-sync.stderr
index 1f698c9..599dcfa 100644
--- a/src/test/ui/fmt/send-sync.stderr
+++ b/src/test/ui/fmt/send-sync.stderr
@@ -1,6 +1,9 @@
 error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
   --> $DIR/send-sync.rs:8:5
    |
+LL | fn send<T: Send>(_: T) {}
+   | ---------------------- required by `send`
+...
 LL |     send(format_args!("{:?}", c));
    |     ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
    |
@@ -12,15 +15,13 @@
    = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&[std::fmt::ArgumentV1<'_>]`
    = note: required because it appears within the type `std::fmt::Arguments<'_>`
-note: required by `send`
-  --> $DIR/send-sync.rs:1:1
-   |
-LL | fn send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
   --> $DIR/send-sync.rs:9:5
    |
+LL | fn sync<T: Sync>(_: T) {}
+   | ---------------------- required by `sync`
+...
 LL |     sync(format_args!("{:?}", c));
    |     ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
    |
@@ -32,11 +33,6 @@
    = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]`
    = note: required because it appears within the type `&[std::fmt::ArgumentV1<'_>]`
    = note: required because it appears within the type `std::fmt::Arguments<'_>`
-note: required by `sync`
-  --> $DIR/send-sync.rs:2:1
-   |
-LL | fn sync<T: Sync>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/fn/fn-trait-formatting.stderr b/src/test/ui/fn/fn-trait-formatting.stderr
index 504bc26..20d7d9e 100644
--- a/src/test/ui/fn/fn-trait-formatting.stderr
+++ b/src/test/ui/fn/fn-trait-formatting.stderr
@@ -28,15 +28,13 @@
 error[E0277]: expected a `std::ops::Fn<(isize,)>` closure, found `{integer}`
   --> $DIR/fn-trait-formatting.rs:19:5
    |
+LL | fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
+   | ------------------------------------------------ required by `needs_fn`
+...
 LL |     needs_fn(1);
    |     ^^^^^^^^ expected an `Fn<(isize,)>` closure, found `{integer}`
    |
    = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `{integer}`
-note: required by `needs_fn`
-  --> $DIR/fn-trait-formatting.rs:3:1
-   |
-LL | fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs
index 43b1a04..0fbc796 100644
--- a/src/test/ui/for/for-c-in-str.rs
+++ b/src/test/ui/for/for-c-in-str.rs
@@ -6,6 +6,6 @@
     //~| NOTE `&str` is not an iterator
     //~| HELP the trait `std::iter::Iterator` is not implemented for `&str`
     //~| NOTE required by `std::iter::IntoIterator::into_iter`
-        println!("");
+        println!();
     }
 }
diff --git a/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr
index 0d77fd4..14aea2d 100644
--- a/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr
+++ b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr
@@ -1,8 +1,8 @@
-error[E0005]: refutable pattern in `for` loop binding: `&std::i32::MIN..=0i32` not covered
+error[E0005]: refutable pattern in `for` loop binding: `&std::i32::MIN..=0i32` and `&2i32..=std::i32::MAX` not covered
   --> $DIR/for-loop-refutable-pattern-error-message.rs:2:9
    |
 LL |     for &1 in [1].iter() {}
-   |         ^^ pattern `&std::i32::MIN..=0i32` not covered
+   |         ^^ patterns `&std::i32::MIN..=0i32` and `&2i32..=std::i32::MAX` not covered
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator-yielding-or-returning-itself.stderr
index 4259168..1049bb6 100644
--- a/src/test/ui/generator-yielding-or-returning-itself.stderr
+++ b/src/test/ui/generator-yielding-or-returning-itself.stderr
@@ -16,20 +16,18 @@
 error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]`
   --> $DIR/generator-yielding-or-returning-itself.rs:28:5
    |
-LL |     want_cyclic_generator_yield(|| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
-   |
-   = note: closures cannot capture themselves or take themselves as argument;
-           this error may be the result of a recent compiler bug-fix,
-           see https://github.com/rust-lang/rust/issues/46062 for more details
-note: required by `want_cyclic_generator_yield`
-  --> $DIR/generator-yielding-or-returning-itself.rs:22:1
-   |
 LL | / pub fn want_cyclic_generator_yield<T>(_: T)
 LL | |     where T: Generator<Yield = T, Return = ()>
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `want_cyclic_generator_yield`
+...
+LL |       want_cyclic_generator_yield(|| {
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+   |
+   = note: closures cannot capture themselves or take themselves as argument;
+           this error may be the result of a recent compiler bug-fix,
+           see https://github.com/rust-lang/rust/issues/46062 for more details
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr
index 92f92e2..dab4d34 100644
--- a/src/test/ui/generator/auto-trait-regions.stderr
+++ b/src/test/ui/generator/auto-trait-regions.stderr
@@ -1,20 +1,26 @@
 error: implementation of `Foo` is not general enough
   --> $DIR/auto-trait-regions.rs:30:5
    |
+LL | auto trait Foo {}
+   | ----------------- trait `Foo` defined here
+...
 LL |     assert_foo(gen);
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`
-   = note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
+   = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`...
+   = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
 
 error: implementation of `Foo` is not general enough
   --> $DIR/auto-trait-regions.rs:48:5
    |
+LL | auto trait Foo {}
+   | ----------------- trait `Foo` defined here
+...
 LL |     assert_foo(gen);
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`
-   = note: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
+   = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
+   = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr
index 7ea9832..51416ce 100644
--- a/src/test/ui/generator/not-send-sync.stderr
+++ b/src/test/ui/generator/not-send-sync.stderr
@@ -1,32 +1,28 @@
 error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
   --> $DIR/not-send-sync.rs:16:5
    |
+LL |     fn assert_send<T: Send>(_: T) {}
+   |     ----------------------------- required by `main::assert_send`
+...
 LL |     assert_send(|| {
    |     ^^^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell<i32>`
    = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell<i32> _]`
-note: required by `main::assert_send`
-  --> $DIR/not-send-sync.rs:7:5
-   |
-LL |     fn assert_send<T: Send>(_: T) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
   --> $DIR/not-send-sync.rs:9:5
    |
+LL |     fn assert_sync<T: Sync>(_: T) {}
+   |     ----------------------------- required by `main::assert_sync`
+...
 LL |     assert_sync(|| {
    |     ^^^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
    |
    = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
    = note: required because it appears within the type `{std::cell::Cell<i32>, ()}`
    = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`
-note: required by `main::assert_sync`
-  --> $DIR/not-send-sync.rs:6:5
-   |
-LL |     fn assert_sync<T: Sync>(_: T) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generator/partial-initialization-across-yield.rs b/src/test/ui/generator/partial-initialization-across-yield.rs
index 1e45930..8b75721 100644
--- a/src/test/ui/generator/partial-initialization-across-yield.rs
+++ b/src/test/ui/generator/partial-initialization-across-yield.rs
@@ -10,7 +10,7 @@
     let _ = || {
         let mut t: (i32, i32);
         t.0 = 42;
-        //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
         yield;
         t.1 = 88;
         let _ = t;
@@ -21,7 +21,7 @@
     let _ = || {
         let mut t: T;
         t.0 = 42;
-        //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
         yield;
         t.1 = 88;
         let _ = t;
@@ -32,7 +32,7 @@
     let _ = || {
         let mut t: S;
         t.x = 42;
-        //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
         yield;
         t.y = 88;
         let _ = t;
diff --git a/src/test/ui/generator/partial-initialization-across-yield.stderr b/src/test/ui/generator/partial-initialization-across-yield.stderr
index 8bf0037..66b8648 100644
--- a/src/test/ui/generator/partial-initialization-across-yield.stderr
+++ b/src/test/ui/generator/partial-initialization-across-yield.stderr
@@ -1,20 +1,20 @@
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/partial-initialization-across-yield.rs:12:9
    |
 LL |         t.0 = 42;
-   |         ^^^^^^^^ use of possibly uninitialized `t`
+   |         ^^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/partial-initialization-across-yield.rs:23:9
    |
 LL |         t.0 = 42;
-   |         ^^^^^^^^ use of possibly uninitialized `t`
+   |         ^^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/partial-initialization-across-yield.rs:34:9
    |
 LL |         t.x = 42;
-   |         ^^^^^^^^ use of possibly uninitialized `t`
+   |         ^^^^^^^^ use of possibly-uninitialized `t`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr
index 404d306..28a6fac 100644
--- a/src/test/ui/generator/static-not-unpin.stderr
+++ b/src/test/ui/generator/static-not-unpin.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]: std::marker::Unpin` is not satisfied
   --> $DIR/static-not-unpin.rs:14:5
    |
+LL | fn assert_unpin<T: Unpin>(_: T) {
+   | ------------------------------- required by `assert_unpin`
+...
 LL |     assert_unpin(generator);
    |     ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]`
-   |
-note: required by `assert_unpin`
-  --> $DIR/static-not-unpin.rs:7:1
-   |
-LL | fn assert_unpin<T: Unpin>(_: T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic/generic-extern.stderr b/src/test/ui/generic/generic-extern.stderr
index e7625ab..c90215b 100644
--- a/src/test/ui/generic/generic-extern.stderr
+++ b/src/test/ui/generic/generic-extern.stderr
@@ -4,7 +4,7 @@
 LL |     fn foo<T>();
    |     ^^^^^^^^^^^^ can't have type parameters
    |
-   = help: use specialization instead of type parameters by replacing them with concrete types like `u32`
+   = help: replace the type parameters with concrete types like `u32`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/due-to-where-clause.rs b/src/test/ui/hrtb/due-to-where-clause.rs
new file mode 100644
index 0000000..04e2ddd
--- /dev/null
+++ b/src/test/ui/hrtb/due-to-where-clause.rs
@@ -0,0 +1,16 @@
+// ignore-compare-mode-nll
+// ^ This code works in nll mode.
+
+fn main() {
+    test::<FooS>(&mut 42); //~ ERROR implementation of `Foo` is not general enough
+}
+
+trait Foo<'a> {}
+
+struct FooS<'a> {
+    data: &'a mut u32,
+}
+
+impl<'a, 'b: 'a> Foo<'b> for FooS<'a> {}
+
+fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
diff --git a/src/test/ui/hrtb/due-to-where-clause.stderr b/src/test/ui/hrtb/due-to-where-clause.stderr
new file mode 100644
index 0000000..e698584
--- /dev/null
+++ b/src/test/ui/hrtb/due-to-where-clause.stderr
@@ -0,0 +1,17 @@
+error: implementation of `Foo` is not general enough
+  --> $DIR/due-to-where-clause.rs:5:5
+   |
+LL |     test::<FooS>(&mut 42);
+   |     ^^^^^^^^^^^^ doesn't satisfy where-clause
+...
+LL | trait Foo<'a> {}
+   | ---------------- trait `Foo` defined here
+...
+LL | fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
+   | ------------------------------------------------------------- due to a where-clause on `test`...
+   |
+   = note: ...`FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`...
+   = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
index 77a5491..003f326 100644
--- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
+++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
@@ -1,11 +1,14 @@
 error: implementation of `Deserialize` is not general enough
   --> $DIR/hrtb-cache-issue-54302.rs:19:5
    |
+LL | trait Deserialize<'de> {}
+   | ------------------------- trait `Deserialize` defined here
+...
 LL |     assert_deserialize_owned::<&'static str>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
    |
-   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
-   = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
+   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
+   = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr
index 20265d6..e0b968b 100644
--- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr
+++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr
@@ -1,19 +1,17 @@
 error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied
   --> $DIR/hrtb-conflate-regions.rs:27:10
    |
-LL | fn b() { want_foo2::<SomeStruct>(); }
-   |          ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct`
-   |
-   = help: the following implementations were found:
-             <SomeStruct as Foo<(&'a isize, &'a isize)>>
-note: required by `want_foo2`
-  --> $DIR/hrtb-conflate-regions.rs:8:1
-   |
 LL | / fn want_foo2<T>()
 LL | |     where T : for<'a,'b> Foo<(&'a isize, &'b isize)>
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `want_foo2`
+...
+LL |   fn b() { want_foo2::<SomeStruct>(); }
+   |            ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct`
+   |
+   = help: the following implementations were found:
+             <SomeStruct as Foo<(&'a isize, &'a isize)>>
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
index 7f2ca03..bc58b8e 100644
--- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
@@ -1,20 +1,18 @@
 error[E0277]: the trait bound `(): Trait<for<'b> fn(&'b u32)>` is not satisfied
   --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
    |
-LL |     foo::<()>();
-   |     ^^^^^^^^^ the trait `Trait<for<'b> fn(&'b u32)>` is not implemented for `()`
-   |
-   = help: the following implementations were found:
-             <() as Trait<fn(&'a u32)>>
-note: required by `foo`
-  --> $DIR/hrtb-exists-forall-trait-contravariant.rs:8:1
-   |
 LL | / fn foo<T>()
 LL | | where
 LL | |     T: Trait<for<'b> fn(&'b u32)>,
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `foo`
+...
+LL |       foo::<()>();
+   |       ^^^^^^^^^ the trait `Trait<for<'b> fn(&'b u32)>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Trait<fn(&'a u32)>>
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr
index cd5982e..441f751 100644
--- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr
@@ -1,20 +1,18 @@
 error[E0277]: the trait bound `(): Trait<for<'b> fn(fn(&'b u32))>` is not satisfied
   --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:5
    |
-LL |     foo::<()>();
-   |     ^^^^^^^^^ the trait `Trait<for<'b> fn(fn(&'b u32))>` is not implemented for `()`
-   |
-   = help: the following implementations were found:
-             <() as Trait<fn(fn(&'a u32))>>
-note: required by `foo`
-  --> $DIR/hrtb-exists-forall-trait-covariant.rs:8:1
-   |
 LL | / fn foo<T>()
 LL | | where
 LL | |     T: Trait<for<'b> fn(fn(&'b u32))>,
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `foo`
+...
+LL |       foo::<()>();
+   |       ^^^^^^^^^ the trait `Trait<for<'b> fn(fn(&'b u32))>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Trait<fn(fn(&'a u32))>>
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr
index f10e427..a119497 100644
--- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr
@@ -1,20 +1,18 @@
 error[E0277]: the trait bound `(): Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not satisfied
   --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
    |
-LL |     foo::<()>();
-   |     ^^^^^^^^^ the trait `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not implemented for `()`
-   |
-   = help: the following implementations were found:
-             <() as Trait<fn(std::cell::Cell<&'a u32>)>>
-note: required by `foo`
-  --> $DIR/hrtb-exists-forall-trait-invariant.rs:10:1
-   |
 LL | / fn foo<T>()
 LL | | where
 LL | |     T: Trait<for<'b> fn(Cell<&'b u32>)>,
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `foo`
+...
+LL |       foo::<()>();
+   |       ^^^^^^^^^ the trait `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Trait<fn(std::cell::Cell<&'a u32>)>>
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
index b5d945f..0cddd353 100644
--- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
@@ -1,18 +1,16 @@
 error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5
    |
-LL |     want_bar_for_any_ccx(b);
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
-   |
-   = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound
-note: required by `want_bar_for_any_ccx`
-  --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:31:1
-   |
 LL | / fn want_bar_for_any_ccx<B>(b: &B)
 LL | |     where B : for<'ccx> Bar<'ccx>
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `want_bar_for_any_ccx`
+...
+LL |       want_bar_for_any_ccx(b);
+   |       ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |
+   = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
index 20a8fd4..6df486e 100644
--- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
@@ -1,31 +1,25 @@
 error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5
    |
-LL |     want_foo_for_any_tcx(f);
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
-   |
-   = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound
-note: required by `want_foo_for_any_tcx`
-  --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1
-   |
+LL |       want_foo_for_any_tcx(f);
+   |       ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
+...
 LL | / fn want_foo_for_any_tcx<F>(f: &F)
 LL | |     where F : for<'tcx> Foo<'tcx>
 LL | | {
 LL | |     want_foo_for_some_tcx(f);
 LL | |     want_foo_for_any_tcx(f);
 LL | | }
-   | |_^
+   | |_- required by `want_foo_for_any_tcx`
+   |
+   = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound
 
 error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:35:5
    |
-LL |     want_bar_for_any_ccx(b);
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
-   |
-   = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound
-note: required by `want_bar_for_any_ccx`
-  --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1
-   |
+LL |       want_bar_for_any_ccx(b);
+   |       ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+...
 LL | / fn want_bar_for_any_ccx<B>(b: &B)
 LL | |     where B : for<'ccx> Bar<'ccx>
 LL | | {
@@ -33,7 +27,9 @@
 ...  |
 LL | |     want_bar_for_any_ccx(b);
 LL | | }
-   | |_^
+   | |_- required by `want_bar_for_any_ccx`
+   |
+   = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr
index 115851d..b2938e5 100644
--- a/src/test/ui/hrtb/hrtb-just-for-static.stderr
+++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr
@@ -1,36 +1,32 @@
 error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied
   --> $DIR/hrtb-just-for-static.rs:24:5
    |
-LL |     want_hrtb::<StaticInt>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt`
-   |
-   = help: the following implementations were found:
-             <StaticInt as Foo<&'static isize>>
-note: required by `want_hrtb`
-  --> $DIR/hrtb-just-for-static.rs:8:1
-   |
 LL | / fn want_hrtb<T>()
 LL | |     where T : for<'a> Foo<&'a isize>
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `want_hrtb`
+...
+LL |       want_hrtb::<StaticInt>()
+   |       ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt`
+   |
+   = help: the following implementations were found:
+             <StaticInt as Foo<&'static isize>>
 
 error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied
   --> $DIR/hrtb-just-for-static.rs:30:5
    |
-LL |     want_hrtb::<&'a u32>()
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32`
-   |
-   = help: the following implementations were found:
-             <&'a u32 as Foo<&'a isize>>
-note: required by `want_hrtb`
-  --> $DIR/hrtb-just-for-static.rs:8:1
-   |
 LL | / fn want_hrtb<T>()
 LL | |     where T : for<'a> Foo<&'a isize>
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `want_hrtb`
+...
+LL |       want_hrtb::<&'a u32>()
+   |       ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32`
+   |
+   = help: the following implementations were found:
+             <&'a u32 as Foo<&'a isize>>
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr
index e7deca7..c0e3fd3 100644
--- a/src/test/ui/hrtb/issue-30786.migrate.stderr
+++ b/src/test/ui/hrtb/issue-30786.migrate.stderr
@@ -1,11 +1,17 @@
 error: implementation of `Stream` is not general enough
   --> $DIR/issue-30786.rs:108:22
    |
-LL |     let map = source.map(|x: &_| x);
-   |                      ^^^
+LL | / pub trait Stream {
+LL | |     type Item;
+LL | |     fn next(self) -> Option<Self::Item>;
+LL | | }
+   | |_- trait `Stream` defined here
+...
+LL |       let map = source.map(|x: &_| x);
+   |                        ^^^ implementation of `Stream` is not general enough
    |
-   = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`
-   = note: but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
+   = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`...
+   = note: ...but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr
index 8614d86..1cfd93e 100644
--- a/src/test/ui/hrtb/issue-30786.nll.stderr
+++ b/src/test/ui/hrtb/issue-30786.nll.stderr
@@ -1,11 +1,11 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-30786.rs:112:18
+  --> $DIR/issue-30786.rs:113:18
    |
 LL |     let filter = map.filter(|x: &_| true);
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-30786.rs:114:17
+  --> $DIR/issue-30786.rs:115:17
    |
 LL |     let count = filter.count(); // Assert that we still have a valid stream.
    |                 ^^^^^^^^^^^^^^
diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs
index b9920a1..c42297c 100644
--- a/src/test/ui/hrtb/issue-30786.rs
+++ b/src/test/ui/hrtb/issue-30786.rs
@@ -16,7 +16,7 @@
 
 //[nll]compile-flags: -Z borrowck=mir
 
-pub trait Stream {
+pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here
     type Item;
     fn next(self) -> Option<Self::Item>;
 }
@@ -109,6 +109,7 @@
     //[migrate]~^ ERROR implementation of `Stream` is not general enough
     //[migrate]~| NOTE  `Stream` would have to be implemented for the type `&'0 mut Map
     //[migrate]~| NOTE  but `Stream` is actually implemented for the type `&'1
+    //[migrate]~| NOTE  implementation of `Stream` is not general enough
     let filter = map.filter(|x: &_| true);
     //[nll]~^ ERROR higher-ranked subtype error
     let count = filter.count(); // Assert that we still have a valid stream.
diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr
index b308291..57eaf2a 100644
--- a/src/test/ui/hrtb/issue-46989.stderr
+++ b/src/test/ui/hrtb/issue-46989.stderr
@@ -1,16 +1,14 @@
 error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied
   --> $DIR/issue-46989.rs:40:5
    |
+LL | fn assert_foo<T: Foo>() {}
+   | ----------------------- required by `assert_foo`
+...
 LL |     assert_foo::<fn(&i32)>();
    |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)`
    |
    = help: the following implementations were found:
              <fn(A) as Foo>
-note: required by `assert_foo`
-  --> $DIR/issue-46989.rs:37:1
-   |
-LL | fn assert_foo<T: Foo>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hrtb/issue-57639.rs b/src/test/ui/hrtb/issue-57639.rs
index 4bcaef3..392e723 100644
--- a/src/test/ui/hrtb/issue-57639.rs
+++ b/src/test/ui/hrtb/issue-57639.rs
@@ -10,7 +10,7 @@
 //
 // See [this comment on GitHub][c] for more details.
 //
-// run-pass
+// check-pass
 //
 // [c]: https://github.com/rust-lang/rust/issues/57639#issuecomment-455685861
 
diff --git a/src/test/ui/hygiene/auxiliary/not-libstd.rs b/src/test/ui/hygiene/auxiliary/not-libstd.rs
new file mode 100644
index 0000000..babba29
--- /dev/null
+++ b/src/test/ui/hygiene/auxiliary/not-libstd.rs
@@ -0,0 +1 @@
+pub fn not_in_lib_std() {}
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.rs b/src/test/ui/hygiene/no_implicit_prelude-2018.rs
index 3ad7435..83ca281 100644
--- a/src/test/ui/hygiene/no_implicit_prelude-2018.rs
+++ b/src/test/ui/hygiene/no_implicit_prelude-2018.rs
@@ -4,7 +4,7 @@
 mod bar {
     fn f() {
         ::std::print!(""); // OK
-        print!(); //~ ERROR cannot find macro `print!` in this scope
+        print!(); //~ ERROR cannot find macro `print` in this scope
     }
 }
 
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
index 0fdb18d..f31b752 100644
--- a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `print!` in this scope
+error: cannot find macro `print` in this scope
   --> $DIR/no_implicit_prelude-2018.rs:7:9
    |
 LL |         print!();
diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs
index 890c830..204e7b2 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.rs
+++ b/src/test/ui/hygiene/no_implicit_prelude.rs
@@ -13,7 +13,7 @@
     }
     fn f() {
         ::foo::m!();
-        assert_eq!(0, 0); //~ ERROR cannot find macro `panic!` in this scope
+        assert_eq!(0, 0); //~ ERROR cannot find macro `panic` in this scope
     }
 }
 
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index 643f803..bc0ce74 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `panic!` in this scope
+error: cannot find macro `panic` in this scope
   --> $DIR/no_implicit_prelude.rs:16:9
    |
 LL |         assert_eq!(0, 0);
@@ -22,7 +22,7 @@
    |              ------------ in this macro invocation
 ...
 LL |         ().clone()
-   |            ^^^^^
+   |            ^^^^^ method not found in `()`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/hygiene/prelude-import-hygiene.rs b/src/test/ui/hygiene/prelude-import-hygiene.rs
new file mode 100644
index 0000000..51e7bed
--- /dev/null
+++ b/src/test/ui/hygiene/prelude-import-hygiene.rs
@@ -0,0 +1,29 @@
+// Make sure that attribute used when injecting the prelude are resolved
+// hygienically.
+
+// check-pass
+// aux-build:not-libstd.rs
+
+//revisions: rust2015 rust2018
+//[rust2018] edition:2018
+
+// The prelude import shouldn't see these as candidates for when it's trying to
+// use the built-in macros.
+extern crate core;
+use core::prelude::v1::test as prelude_import;
+use core::prelude::v1::test as macro_use;
+
+// Should not be used for the prelude import - not a concern in the 2015 edition
+// because `std` is already declared in the crate root.
+#[cfg(rust2018)]
+extern crate not_libstd as std;
+
+#[cfg(rust2018)]
+mod x {
+    // The extern crate item should override `std` in the extern prelude.
+    fn f() {
+        std::not_in_lib_std();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr
index 4192b97..39e3252 100644
--- a/src/test/ui/hygiene/trait_items.stderr
+++ b/src/test/ui/hygiene/trait_items.stderr
@@ -5,7 +5,7 @@
    |              ------------ in this macro invocation
 ...
 LL |     pub macro m() { ().f() }
-   |                        ^
+   |                        ^ method not found in `()`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout
index beac4c1..6971873 100644
--- a/src/test/ui/hygiene/unpretty-debug.stdout
+++ b/src/test/ui/hygiene/unpretty-debug.stdout
@@ -13,3 +13,13 @@
 fn bar /* 0#0 */() { let x /* 0#0 */ = 1; y /* 0#1 */ + x /* 0#0 */ }
 
 fn y /* 0#0 */() { }
+
+/*
+Expansions:
+0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root
+1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, foo)
+
+SyntaxContexts:
+#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
+#1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent)
+*/
diff --git a/src/test/ui/if-ret.stderr b/src/test/ui/if-ret.stderr
new file mode 100644
index 0000000..73402e5
--- /dev/null
+++ b/src/test/ui/if-ret.stderr
@@ -0,0 +1,8 @@
+warning: unreachable block in `if` expression
+  --> $DIR/if-ret.rs:6:24
+   |
+LL | fn foo() { if (return) { } }
+   |                        ^^^
+   |
+   = note: `#[warn(unreachable_code)]` on by default
+
diff --git a/src/test/ui/if/if-without-else-as-fn-expr.rs b/src/test/ui/if/if-without-else-as-fn-expr.rs
index 15892de..826371b 100644
--- a/src/test/ui/if/if-without-else-as-fn-expr.rs
+++ b/src/test/ui/if/if-without-else-as-fn-expr.rs
@@ -3,7 +3,6 @@
         return 3;
     }
     //~^^^ ERROR if may be missing an else clause
-    //~| ERROR mismatched types [E0308]
 }
 
 fn foo2(bar: usize) -> usize {
@@ -11,7 +10,6 @@
         return 3;
     };
     //~^^^ ERROR if may be missing an else clause
-    //~| ERROR mismatched types [E0308]
     x
 }
 
@@ -20,7 +18,6 @@
         3
     }
     //~^^^ ERROR if may be missing an else clause
-    //~| ERROR mismatched types [E0308]
 }
 
 fn foo_let(bar: usize) -> usize {
@@ -28,7 +25,6 @@
         return 3;
     }
     //~^^^ ERROR if may be missing an else clause
-    //~| ERROR mismatched types [E0308]
 }
 
 fn foo2_let(bar: usize) -> usize {
@@ -36,7 +32,6 @@
         return 3;
     };
     //~^^^ ERROR if may be missing an else clause
-    //~| ERROR mismatched types [E0308]
     x
 }
 
@@ -45,7 +40,6 @@
         3
     }
     //~^^^ ERROR if may be missing an else clause
-    //~| ERROR mismatched types [E0308]
 }
 
 // FIXME(60254): deduplicate first error in favor of second.
diff --git a/src/test/ui/if/if-without-else-as-fn-expr.stderr b/src/test/ui/if/if-without-else-as-fn-expr.stderr
index 06600b1..b49c2aa 100644
--- a/src/test/ui/if/if-without-else-as-fn-expr.stderr
+++ b/src/test/ui/if/if-without-else-as-fn-expr.stderr
@@ -1,14 +1,3 @@
-error[E0308]: mismatched types
-  --> $DIR/if-without-else-as-fn-expr.rs:2:5
-   |
-LL | /     if bar % 5 == 0 {
-LL | |         return 3;
-LL | |     }
-   | |_____^ expected usize, found ()
-   |
-   = note: expected type `usize`
-              found type `()`
-
 error[E0317]: if may be missing an else clause
   --> $DIR/if-without-else-as-fn-expr.rs:2:5
    |
@@ -24,20 +13,8 @@
    = note: `if` expressions without `else` evaluate to `()`
    = help: consider adding an `else` block that evaluates to the expected type
 
-error[E0308]: mismatched types
-  --> $DIR/if-without-else-as-fn-expr.rs:10:20
-   |
-LL |       let x: usize = if bar % 5 == 0 {
-   |  ____________________^
-LL | |         return 3;
-LL | |     };
-   | |_____^ expected usize, found ()
-   |
-   = note: expected type `usize`
-              found type `()`
-
 error[E0317]: if may be missing an else clause
-  --> $DIR/if-without-else-as-fn-expr.rs:10:20
+  --> $DIR/if-without-else-as-fn-expr.rs:9:20
    |
 LL |       let x: usize = if bar % 5 == 0 {
    |  _________-__________^
@@ -52,19 +29,8 @@
    = note: `if` expressions without `else` evaluate to `()`
    = help: consider adding an `else` block that evaluates to the expected type
 
-error[E0308]: mismatched types
-  --> $DIR/if-without-else-as-fn-expr.rs:19:5
-   |
-LL | /     if bar % 5 == 0 {
-LL | |         3
-LL | |     }
-   | |_____^ expected usize, found ()
-   |
-   = note: expected type `usize`
-              found type `()`
-
 error[E0317]: if may be missing an else clause
-  --> $DIR/if-without-else-as-fn-expr.rs:19:5
+  --> $DIR/if-without-else-as-fn-expr.rs:17:5
    |
 LL |   fn foo3(bar: usize) -> usize {
    |                          ----- expected `usize` because of this return type
@@ -78,19 +44,8 @@
    = note: `if` expressions without `else` evaluate to `()`
    = help: consider adding an `else` block that evaluates to the expected type
 
-error[E0308]: mismatched types
-  --> $DIR/if-without-else-as-fn-expr.rs:27:5
-   |
-LL | /     if let 0 = 1 {
-LL | |         return 3;
-LL | |     }
-   | |_____^ expected usize, found ()
-   |
-   = note: expected type `usize`
-              found type `()`
-
 error[E0317]: if may be missing an else clause
-  --> $DIR/if-without-else-as-fn-expr.rs:27:5
+  --> $DIR/if-without-else-as-fn-expr.rs:24:5
    |
 LL |   fn foo_let(bar: usize) -> usize {
    |                             ----- expected `usize` because of this return type
@@ -104,20 +59,8 @@
    = note: `if` expressions without `else` evaluate to `()`
    = help: consider adding an `else` block that evaluates to the expected type
 
-error[E0308]: mismatched types
-  --> $DIR/if-without-else-as-fn-expr.rs:35:20
-   |
-LL |       let x: usize = if let 0 = 1 {
-   |  ____________________^
-LL | |         return 3;
-LL | |     };
-   | |_____^ expected usize, found ()
-   |
-   = note: expected type `usize`
-              found type `()`
-
 error[E0317]: if may be missing an else clause
-  --> $DIR/if-without-else-as-fn-expr.rs:35:20
+  --> $DIR/if-without-else-as-fn-expr.rs:31:20
    |
 LL |       let x: usize = if let 0 = 1 {
    |  _________-__________^
@@ -132,19 +75,8 @@
    = note: `if` expressions without `else` evaluate to `()`
    = help: consider adding an `else` block that evaluates to the expected type
 
-error[E0308]: mismatched types
-  --> $DIR/if-without-else-as-fn-expr.rs:44:5
-   |
-LL | /     if let 0 = 1 {
-LL | |         3
-LL | |     }
-   | |_____^ expected usize, found ()
-   |
-   = note: expected type `usize`
-              found type `()`
-
 error[E0317]: if may be missing an else clause
-  --> $DIR/if-without-else-as-fn-expr.rs:44:5
+  --> $DIR/if-without-else-as-fn-expr.rs:39:5
    |
 LL |   fn foo3_let(bar: usize) -> usize {
    |                              ----- expected `usize` because of this return type
@@ -158,7 +90,6 @@
    = note: `if` expressions without `else` evaluate to `()`
    = help: consider adding an `else` block that evaluates to the expected type
 
-error: aborting due to 12 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0308, E0317.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0317`.
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index 61450d3..af641a8 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -72,16 +72,14 @@
 error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
   --> $DIR/auto-trait-leak.rs:15:5
    |
+LL | fn send<T: Send>(_: T) {}
+   | ---------------------- required by `send`
+...
 LL |     send(cycle2().clone());
    |     ^^^^ `std::rc::Rc<std::string::String>` cannot be sent between threads safely
    |
    = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
    = note: required because it appears within the type `impl std::clone::Clone`
-note: required by `send`
-  --> $DIR/auto-trait-leak.rs:4:1
-   |
-LL | fn send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr
index 19899ff..460af7d 100644
--- a/src/test/ui/impl-trait/auto-trait-leak2.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr
@@ -1,32 +1,28 @@
 error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
   --> $DIR/auto-trait-leak2.rs:13:5
    |
+LL | fn send<T: Send>(_: T) {}
+   | ---------------------- required by `send`
+...
 LL |     send(before());
    |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
    |
    = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
    = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
    = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
-note: required by `send`
-  --> $DIR/auto-trait-leak2.rs:10:1
-   |
-LL | fn send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
   --> $DIR/auto-trait-leak2.rs:16:5
    |
+LL | fn send<T: Send>(_: T) {}
+   | ---------------------- required by `send`
+...
 LL |     send(after());
    |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
    |
    = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
    = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
    = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
-note: required by `send`
-  --> $DIR/auto-trait-leak2.rs:10:1
-   |
-LL | fn send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr
index ad10817..644d26b 100644
--- a/src/test/ui/impl-trait/bindings-opaque.stderr
+++ b/src/test/ui/impl-trait/bindings-opaque.stderr
@@ -10,19 +10,19 @@
   --> $DIR/bindings-opaque.rs:11:17
    |
 LL |     let _ = FOO.count_ones();
-   |                 ^^^^^^^^^^
+   |                 ^^^^^^^^^^ method not found in `impl std::marker::Copy`
 
 error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
   --> $DIR/bindings-opaque.rs:13:17
    |
 LL |     let _ = BAR.count_ones();
-   |                 ^^^^^^^^^^
+   |                 ^^^^^^^^^^ method not found in `impl std::marker::Copy`
 
 error[E0599]: no method named `count_ones` found for type `impl std::marker::Copy` in the current scope
   --> $DIR/bindings-opaque.rs:15:17
    |
 LL |     let _ = foo.count_ones();
-   |                 ^^^^^^^^^^
+   |                 ^^^^^^^^^^ method not found in `impl std::marker::Copy`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/impl-trait/closure-calling-parent-fn.rs b/src/test/ui/impl-trait/closure-calling-parent-fn.rs
index 58d7875..9dab334 100644
--- a/src/test/ui/impl-trait/closure-calling-parent-fn.rs
+++ b/src/test/ui/impl-trait/closure-calling-parent-fn.rs
@@ -5,7 +5,7 @@
 // `foo` and hence is treated opaquely within the closure body.  This
 // resulted in a failed subtype relationship.
 //
-// run-pass
+// check-pass
 
 fn foo() -> impl Copy { || foo(); }
 fn bar() -> impl Copy { || bar(); }
diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
index 666418f..441191b 100644
--- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
+++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr
@@ -5,7 +5,7 @@
    | ----------- method `foo` not found for this
 ...
 LL |     f1.foo(1usize);
-   |        ^^^
+   |        ^^^ method not found in `Bar`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `foo`, perhaps you need to implement it:
diff --git a/src/test/ui/impl-trait/issues/issue-53457.rs b/src/test/ui/impl-trait/issues/issue-53457.rs
index de8c579..3f97502 100644
--- a/src/test/ui/impl-trait/issues/issue-53457.rs
+++ b/src/test/ui/impl-trait/issues/issue-53457.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 #![feature(type_alias_impl_trait)]
 
@@ -9,7 +9,7 @@
 }
 
 fn foo() -> X {
-    bar(|x| ())
+    bar(|_| ())
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
index afb33766..fb870d6 100644
--- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
+++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
@@ -5,7 +5,7 @@
    | ----------- method `is_empty` not found for this
 ...
 LL |     foo(|s| s.is_empty());
-   |               ^^^^^^^^
+   |               ^^^^^^^^ method not found in `Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `is_empty`, perhaps you need to implement it:
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs
index 2da3886..3911769 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs
+++ b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs
@@ -1,5 +1,5 @@
 // edition:2018
-// run-pass
+// check-pass
 // revisions: migrate mir
 //[mir]compile-flags: -Z borrowck=mir
 
diff --git a/src/test/ui/impl-trait/needs_least_region_or_bound.rs b/src/test/ui/impl-trait/needs_least_region_or_bound.rs
index 52475f6..3c8682b 100644
--- a/src/test/ui/impl-trait/needs_least_region_or_bound.rs
+++ b/src/test/ui/impl-trait/needs_least_region_or_bound.rs
@@ -1,9 +1,7 @@
-// run-pass
+// check-pass
 
 #![feature(member_constraints)]
 
-use std::fmt::Debug;
-
 trait MultiRegionTrait<'a, 'b> {}
 impl<'a, 'b> MultiRegionTrait<'a, 'b> for (&'a u32, &'b u32) {}
 
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
index d980d7c..be8f3ab 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -2,7 +2,7 @@
   --> $DIR/no-method-suggested-traits.rs:23:10
    |
 LL |     1u32.method();
-   |          ^^^^^^
+   |          ^^^^^^ method not found in `u32`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following traits are implemented but not in scope, perhaps add a `use` for one of them:
@@ -20,7 +20,7 @@
   --> $DIR/no-method-suggested-traits.rs:26:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1u32)).method();
-   |                                            ^^^^^^
+   |                                            ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u32>>`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following traits are implemented but not in scope, perhaps add a `use` for one of them:
@@ -38,7 +38,7 @@
   --> $DIR/no-method-suggested-traits.rs:30:9
    |
 LL |     'a'.method();
-   |         ^^^^^^
+   |         ^^^^^^ method not found in `char`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope, perhaps add a `use` for it:
@@ -49,8 +49,16 @@
 error[E0599]: no method named `method` found for type `std::rc::Rc<&mut std::boxed::Box<&char>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:32:43
    |
+LL |         fn method(&self) {}
+   |            ------
+   |            |
+   |            the method is available for `std::boxed::Box<std::rc::Rc<&mut std::boxed::Box<&char>>>` here
+   |            the method is available for `std::pin::Pin<std::rc::Rc<&mut std::boxed::Box<&char>>>` here
+   |            the method is available for `std::sync::Arc<std::rc::Rc<&mut std::boxed::Box<&char>>>` here
+   |            the method is available for `std::rc::Rc<std::rc::Rc<&mut std::boxed::Box<&char>>>` here
+...
 LL |     std::rc::Rc::new(&mut Box::new(&'a')).method();
-   |                                           ^^^^^^
+   |                                           ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&char>>`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope, perhaps add a `use` for it:
@@ -62,7 +70,7 @@
   --> $DIR/no-method-suggested-traits.rs:35:10
    |
 LL |     1i32.method();
-   |          ^^^^^^
+   |          ^^^^^^ method not found in `i32`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope, perhaps add a `use` for it:
@@ -74,7 +82,7 @@
   --> $DIR/no-method-suggested-traits.rs:37:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1i32)).method();
-   |                                            ^^^^^^
+   |                                            ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&i32>>`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope, perhaps add a `use` for it:
@@ -89,7 +97,7 @@
    | ----------- method `method` not found for this
 ...
 LL |     Foo.method();
-   |         ^^^^^^
+   |         ^^^^^^ method not found in `Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following traits define an item `method`, perhaps you need to implement one of them:
@@ -102,7 +110,7 @@
   --> $DIR/no-method-suggested-traits.rs:42:43
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method();
-   |                                           ^^^^^^
+   |                                           ^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&Foo>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following traits define an item `method`, perhaps you need to implement one of them:
@@ -115,7 +123,7 @@
   --> $DIR/no-method-suggested-traits.rs:45:10
    |
 LL |     1u64.method2();
-   |          ^^^^^^^
+   |          ^^^^^^^ method not found in `u64`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
@@ -125,7 +133,7 @@
   --> $DIR/no-method-suggested-traits.rs:47:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1u64)).method2();
-   |                                            ^^^^^^^
+   |                                            ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
@@ -135,7 +143,7 @@
   --> $DIR/no-method-suggested-traits.rs:50:37
    |
 LL |     no_method_suggested_traits::Foo.method2();
-   |                                     ^^^^^^^
+   |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
@@ -145,7 +153,7 @@
   --> $DIR/no-method-suggested-traits.rs:52:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
-   |                                                                       ^^^^^^^
+   |                                                                       ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
@@ -155,7 +163,7 @@
   --> $DIR/no-method-suggested-traits.rs:54:40
    |
 LL |     no_method_suggested_traits::Bar::X.method2();
-   |                                        ^^^^^^^
+   |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
@@ -165,7 +173,7 @@
   --> $DIR/no-method-suggested-traits.rs:56:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
-   |                                                                          ^^^^^^^
+   |                                                                          ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method2`, perhaps you need to implement it:
@@ -178,7 +186,7 @@
    | ----------- method `method3` not found for this
 ...
 LL |     Foo.method3();
-   |         ^^^^^^^
+   |         ^^^^^^^ method not found in `Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
@@ -188,7 +196,7 @@
   --> $DIR/no-method-suggested-traits.rs:61:43
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Foo)).method3();
-   |                                           ^^^^^^^
+   |                                           ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&Foo>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
@@ -201,7 +209,7 @@
    | -------- method `method3` not found for this
 ...
 LL |     Bar::X.method3();
-   |            ^^^^^^^
+   |            ^^^^^^^ method not found in `Bar`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
@@ -211,7 +219,7 @@
   --> $DIR/no-method-suggested-traits.rs:65:46
    |
 LL |     std::rc::Rc::new(&mut Box::new(&Bar::X)).method3();
-   |                                              ^^^^^^^
+   |                                              ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&Bar>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `method3`, perhaps you need to implement it:
@@ -221,37 +229,37 @@
   --> $DIR/no-method-suggested-traits.rs:69:13
    |
 LL |     1_usize.method3();
-   |             ^^^^^^^
+   |             ^^^^^^^ method not found in `usize`
 
 error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&usize>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:70:47
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
-   |                                               ^^^^^^^
+   |                                               ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&usize>>`
 
 error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:71:37
    |
 LL |     no_method_suggested_traits::Foo.method3();
-   |                                     ^^^^^^^
+   |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
 
 error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:72:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
-   |                                                                       ^^^^^^^
+   |                                                                       ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>`
 
 error[E0599]: no method named `method3` found for type `no_method_suggested_traits::Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:74:40
    |
 LL |     no_method_suggested_traits::Bar::X.method3();
-   |                                        ^^^^^^^
+   |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
 
 error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:75:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
-   |                                                                          ^^^^^^^
+   |                                                                          ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>`
 
 error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs
new file mode 100644
index 0000000..cfd9c0e
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs
@@ -0,0 +1,25 @@
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden. Even when there's an opaque type in another crate
+// hiding this.
+
+fn id<T>(t: T) -> impl Sized { t }
+
+fn recursive_id() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+    id(recursive_id2())
+}
+
+fn recursive_id2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+    id(recursive_id())
+}
+
+fn wrap<T>(t: T) -> impl Sized { (t,) }
+
+fn recursive_wrap() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+    wrap(recursive_wrap2())
+}
+
+fn recursive_wrap2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+    wrap(recursive_wrap())
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr
new file mode 100644
index 0000000..7572c6c
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr
@@ -0,0 +1,35 @@
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:7:22
+   |
+LL | fn recursive_id() -> impl Sized {
+   |                      ^^^^^^^^^^ expands to a recursive type
+   |
+   = note: type resolves to itself
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:11:23
+   |
+LL | fn recursive_id2() -> impl Sized {
+   |                       ^^^^^^^^^^ expands to a recursive type
+   |
+   = note: type resolves to itself
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:17:24
+   |
+LL | fn recursive_wrap() -> impl Sized {
+   |                        ^^^^^^^^^^ expands to a recursive type
+   |
+   = note: expanded type is `((impl Sized,),)`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:21:25
+   |
+LL | fn recursive_wrap2() -> impl Sized {
+   |                         ^^^^^^^^^^ expands to a recursive type
+   |
+   = note: expanded type is `((impl Sized,),)`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/imports/gensymed.rs b/src/test/ui/imports/gensymed.rs
index 613ccc0..7b53f0c 100644
--- a/src/test/ui/imports/gensymed.rs
+++ b/src/test/ui/imports/gensymed.rs
@@ -1,7 +1,9 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // edition:2018
 // aux-build:gensymed.rs
 
 extern crate gensymed;
 
+use gensymed::*;
+
 fn main() {}
diff --git a/src/test/ui/imports/unresolved-imports-used.rs b/src/test/ui/imports/unresolved-imports-used.rs
index d1461e7..75cf880 100644
--- a/src/test/ui/imports/unresolved-imports-used.rs
+++ b/src/test/ui/imports/unresolved-imports-used.rs
@@ -1,12 +1,18 @@
-// There should be *no* unused import errors.
+// There should be *one* unused import error.
 #![deny(unused_imports)]
 
 mod qux {
    fn quz() {}
+   pub fn quy() {}
 }
 
-use qux::quz; //~ ERROR function `quz` is private
-use qux::bar; //~ ERROR unresolved import `qux::bar`
-use foo::bar; //~ ERROR unresolved import `foo`
+use qux::quz;  //~ ERROR function `quz` is private
+use qux::bar;  //~ ERROR unresolved import `qux::bar`
+use foo::bar;  //~ ERROR unresolved import `foo`
+use baz::*;    //~ ERROR unresolved import `baz`
+use qux::bar2; //~ ERROR unresolved import `qux::bar2`
+use foo2::bar2;//~ ERROR unresolved import `foo2`
+use baz2::*;   //~ ERROR unresolved import `baz2`
+use qux::quy;  //~ ERROR unused import
 
 fn main() {}
diff --git a/src/test/ui/imports/unresolved-imports-used.stderr b/src/test/ui/imports/unresolved-imports-used.stderr
index e8c827a..b341e8e 100644
--- a/src/test/ui/imports/unresolved-imports-used.stderr
+++ b/src/test/ui/imports/unresolved-imports-used.stderr
@@ -1,22 +1,58 @@
 error[E0432]: unresolved import `qux::bar`
-  --> $DIR/unresolved-imports-used.rs:9:5
+  --> $DIR/unresolved-imports-used.rs:10:5
    |
 LL | use qux::bar;
    |     ^^^^^^^^ no `bar` in `qux`
 
+error[E0432]: unresolved import `qux::bar2`
+  --> $DIR/unresolved-imports-used.rs:13:5
+   |
+LL | use qux::bar2;
+   |     ^^^^^^^^^ no `bar2` in `qux`
+
 error[E0432]: unresolved import `foo`
-  --> $DIR/unresolved-imports-used.rs:10:5
+  --> $DIR/unresolved-imports-used.rs:11:5
    |
 LL | use foo::bar;
    |     ^^^ maybe a missing crate `foo`?
 
+error[E0432]: unresolved import `baz`
+  --> $DIR/unresolved-imports-used.rs:12:5
+   |
+LL | use baz::*;
+   |     ^^^ maybe a missing crate `baz`?
+
+error[E0432]: unresolved import `foo2`
+  --> $DIR/unresolved-imports-used.rs:14:5
+   |
+LL | use foo2::bar2;
+   |     ^^^^ maybe a missing crate `foo2`?
+
+error[E0432]: unresolved import `baz2`
+  --> $DIR/unresolved-imports-used.rs:15:5
+   |
+LL | use baz2::*;
+   |     ^^^^ maybe a missing crate `baz2`?
+
 error[E0603]: function `quz` is private
-  --> $DIR/unresolved-imports-used.rs:8:10
+  --> $DIR/unresolved-imports-used.rs:9:10
    |
 LL | use qux::quz;
    |          ^^^
 
-error: aborting due to 3 previous errors
+error: unused import: `qux::quy`
+  --> $DIR/unresolved-imports-used.rs:16:5
+   |
+LL | use qux::quy;
+   |     ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unresolved-imports-used.rs:2:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0432, E0603.
 For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/inaccessible-test-modules.rs b/src/test/ui/inaccessible-test-modules.rs
deleted file mode 100644
index 7095ec2..0000000
--- a/src/test/ui/inaccessible-test-modules.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// compile-flags:--test
-
-// the `--test` harness creates modules with these textual names, but
-// they should be inaccessible from normal code.
-use __test as x; //~ ERROR unresolved import `__test`
-use __test_reexports as y; //~ ERROR unresolved import `__test_reexports`
-
-#[test]
-fn baz() {}
diff --git a/src/test/ui/inaccessible-test-modules.stderr b/src/test/ui/inaccessible-test-modules.stderr
deleted file mode 100644
index b6a817e..0000000
--- a/src/test/ui/inaccessible-test-modules.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0432]: unresolved import `__test`
-  --> $DIR/inaccessible-test-modules.rs:5:5
-   |
-LL | use __test as x;
-   |     ------^^^^^
-   |     |
-   |     no `__test` in the root
-   |     help: a similar name exists in the module: `test`
-
-error[E0432]: unresolved import `__test_reexports`
-  --> $DIR/inaccessible-test-modules.rs:6:5
-   |
-LL | use __test_reexports as y;
-   |     ----------------^^^^^
-   |     |
-   |     no `__test_reexports` in the root
-   |     help: a similar name exists in the module: `__test_reexports`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr
index 3159a4b..a2ad58a7 100644
--- a/src/test/ui/infinite/infinite-autoderef.stderr
+++ b/src/test/ui/infinite/infinite-autoderef.stderr
@@ -44,7 +44,7 @@
    | ----------- method `bar` not found for this
 ...
 LL |     Foo.bar();
-   |         ^^^
+   |         ^^^ method not found in `Foo`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/intrinsics-always-extern.rs b/src/test/ui/intrinsics-always-extern.rs
new file mode 100644
index 0000000..2295114
--- /dev/null
+++ b/src/test/ui/intrinsics-always-extern.rs
@@ -0,0 +1,16 @@
+#![feature(intrinsics)]
+
+trait Foo {
+    extern "rust-intrinsic" fn foo(&self); //~ ERROR intrinsic must
+}
+
+impl Foo for () {
+    extern "rust-intrinsic" fn foo(&self) { //~ ERROR intrinsic must
+    }
+}
+
+extern "rust-intrinsic" fn hello() {//~ ERROR intrinsic must
+}
+
+fn main() {
+}
diff --git a/src/test/ui/intrinsics-always-extern.stderr b/src/test/ui/intrinsics-always-extern.stderr
new file mode 100644
index 0000000..24b6da1
--- /dev/null
+++ b/src/test/ui/intrinsics-always-extern.stderr
@@ -0,0 +1,24 @@
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/intrinsics-always-extern.rs:4:32
+   |
+LL |     extern "rust-intrinsic" fn foo(&self);
+   |                                ^^^
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/intrinsics-always-extern.rs:8:43
+   |
+LL |       extern "rust-intrinsic" fn foo(&self) {
+   |  ___________________________________________^
+LL | |     }
+   | |_____^
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/intrinsics-always-extern.rs:12:36
+   |
+LL |   extern "rust-intrinsic" fn hello() {
+   |  ____________________________________^
+LL | | }
+   | |_^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issues/issue-10465.stderr b/src/test/ui/issues/issue-10465.stderr
index 6efbd8e..413daa6 100644
--- a/src/test/ui/issues/issue-10465.stderr
+++ b/src/test/ui/issues/issue-10465.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-10465.rs:17:15
    |
 LL |             b.foo();
-   |               ^^^
+   |               ^^^ method not found in `&b::B`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/issues/issue-11692-1.rs b/src/test/ui/issues/issue-11692-1.rs
index 70b712c..b6f3bb8 100644
--- a/src/test/ui/issues/issue-11692-1.rs
+++ b/src/test/ui/issues/issue-11692-1.rs
@@ -1,3 +1,3 @@
 fn main() {
-    print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope
+    print!(testo!()); //~ ERROR cannot find macro `testo` in this scope
 }
diff --git a/src/test/ui/issues/issue-11692-1.stderr b/src/test/ui/issues/issue-11692-1.stderr
index bfd1647..3864634 100644
--- a/src/test/ui/issues/issue-11692-1.stderr
+++ b/src/test/ui/issues/issue-11692-1.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `testo!` in this scope
+error: cannot find macro `testo` in this scope
   --> $DIR/issue-11692-1.rs:2:12
    |
 LL |     print!(testo!());
diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs
index 61be284..5957ed3 100644
--- a/src/test/ui/issues/issue-11692-2.rs
+++ b/src/test/ui/issues/issue-11692-2.rs
@@ -1,3 +1,3 @@
 fn main() {
-    concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
+    concat!(test!()); //~ ERROR cannot find macro `test` in this scope
 }
diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr
index 740c355..f021943 100644
--- a/src/test/ui/issues/issue-11692-2.stderr
+++ b/src/test/ui/issues/issue-11692-2.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `test!` in this scope
+error: cannot find macro `test` in this scope
   --> $DIR/issue-11692-2.rs:2:13
    |
 LL |     concat!(test!());
diff --git a/src/test/ui/issues/issue-1251.rs b/src/test/ui/issues/issue-1251.rs
index 63b5a4d..77278ec 100644
--- a/src/test/ui/issues/issue-1251.rs
+++ b/src/test/ui/issues/issue-1251.rs
@@ -6,8 +6,6 @@
 
 #![feature(rustc_private)]
 
-#![crate_id="rust_get_test_int"]
-
 mod rustrt {
     extern crate libc;
 
diff --git a/src/test/ui/issues/issue-13853.stderr b/src/test/ui/issues/issue-13853.stderr
index 9026845..c57ca3e 100644
--- a/src/test/ui/issues/issue-13853.stderr
+++ b/src/test/ui/issues/issue-13853.stderr
@@ -14,7 +14,7 @@
   --> $DIR/issue-13853.rs:27:23
    |
 LL |     for node in graph.iter() {
-   |                       ^^^^
+   |                       ^^^^ method not found in `&G`
 
 error[E0308]: mismatched types
   --> $DIR/issue-13853.rs:37:13
diff --git a/src/test/ui/issues/issue-14309.rs b/src/test/ui/issues/issue-14309.rs
index d0e532a..328a4c9 100644
--- a/src/test/ui/issues/issue-14309.rs
+++ b/src/test/ui/issues/issue-14309.rs
@@ -27,7 +27,7 @@
 }
 
 extern "C" {
-    fn foo(x: A); //~ ERROR type `A` which is not FFI-safe
+    fn foo(x: A); //~ ERROR type `A`, which is not FFI-safe
     fn bar(x: B); //~ ERROR type `A`
     fn baz(x: C);
     fn qux(x: A2); //~ ERROR type `A`
diff --git a/src/test/ui/issues/issue-14309.stderr b/src/test/ui/issues/issue-14309.stderr
index e049109..f598e1f 100644
--- a/src/test/ui/issues/issue-14309.stderr
+++ b/src/test/ui/issues/issue-14309.stderr
@@ -1,8 +1,8 @@
-error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+error: `extern` block uses type `A`, which is not FFI-safe
   --> $DIR/issue-14309.rs:30:15
    |
 LL |     fn foo(x: A);
-   |               ^
+   |               ^ not FFI-safe
    |
 note: lint level defined here
   --> $DIR/issue-14309.rs:1:9
@@ -10,6 +10,7 @@
 LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 note: type defined here
   --> $DIR/issue-14309.rs:4:1
    |
@@ -18,13 +19,14 @@
 LL | | }
    | |_^
 
-error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+error: `extern` block uses type `A`, which is not FFI-safe
   --> $DIR/issue-14309.rs:31:15
    |
 LL |     fn bar(x: B);
-   |               ^
+   |               ^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 note: type defined here
   --> $DIR/issue-14309.rs:4:1
    |
@@ -33,13 +35,14 @@
 LL | | }
    | |_^
 
-error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+error: `extern` block uses type `A`, which is not FFI-safe
   --> $DIR/issue-14309.rs:33:15
    |
 LL |     fn qux(x: A2);
-   |               ^^
+   |               ^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 note: type defined here
   --> $DIR/issue-14309.rs:4:1
    |
@@ -48,13 +51,14 @@
 LL | | }
    | |_^
 
-error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+error: `extern` block uses type `A`, which is not FFI-safe
   --> $DIR/issue-14309.rs:34:16
    |
 LL |     fn quux(x: B2);
-   |                ^^
+   |                ^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 note: type defined here
   --> $DIR/issue-14309.rs:4:1
    |
@@ -63,13 +67,14 @@
 LL | | }
    | |_^
 
-error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
+error: `extern` block uses type `A`, which is not FFI-safe
   --> $DIR/issue-14309.rs:36:16
    |
 LL |     fn fred(x: D);
-   |                ^
+   |                ^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 note: type defined here
   --> $DIR/issue-14309.rs:4:1
    |
diff --git a/src/test/ui/issues/issue-15207.stderr b/src/test/ui/issues/issue-15207.stderr
index 2d90eb8..25ce7cb 100644
--- a/src/test/ui/issues/issue-15207.stderr
+++ b/src/test/ui/issues/issue-15207.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-15207.rs:3:15
    |
 LL |         break.push(1)
-   |               ^^^^
+   |               ^^^^ method not found in `!`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-15381.rs b/src/test/ui/issues/issue-15381.rs
index d21c321..5307153 100644
--- a/src/test/ui/issues/issue-15381.rs
+++ b/src/test/ui/issues/issue-15381.rs
@@ -2,8 +2,8 @@
     let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
 
     for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
-        //~^ ERROR refutable pattern in `for` loop binding: `&[]` not covered
+        //~^ ERROR refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not
         println!("y={}", y);
-        //~^ ERROR borrow of possibly uninitialized variable: `y`
+        //~^ ERROR borrow of possibly-uninitialized variable: `y`
     }
 }
diff --git a/src/test/ui/issues/issue-15381.stderr b/src/test/ui/issues/issue-15381.stderr
index a849584..47a0d51 100644
--- a/src/test/ui/issues/issue-15381.stderr
+++ b/src/test/ui/issues/issue-15381.stderr
@@ -1,14 +1,14 @@
-error[E0005]: refutable pattern in `for` loop binding: `&[]` not covered
+error[E0005]: refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
   --> $DIR/issue-15381.rs:4:9
    |
 LL |     for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
-   |         ^^^^^^^^ pattern `&[]` not covered
+   |         ^^^^^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
 
-error[E0381]: borrow of possibly uninitialized variable: `y`
+error[E0381]: borrow of possibly-uninitialized variable: `y`
   --> $DIR/issue-15381.rs:6:26
    |
 LL |         println!("y={}", y);
-   |                          ^ use of possibly uninitialized `y`
+   |                          ^ use of possibly-uninitialized `y`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-15783.rs b/src/test/ui/issues/issue-15783.rs
index 77eae91..5189f55 100644
--- a/src/test/ui/issues/issue-15783.rs
+++ b/src/test/ui/issues/issue-15783.rs
@@ -6,9 +6,9 @@
     let name = "Foo";
     let x = Some(&[name]);
     let msg = foo(x);
-//~^ ERROR mismatched types
-//~| expected type `std::option::Option<&[&str]>`
-//~| found type `std::option::Option<&[&str; 1]>`
-//~| expected slice, found array of 1 elements
+    //~^ ERROR mismatched types
+    //~| expected type `std::option::Option<&[&str]>`
+    //~| found type `std::option::Option<&[&str; 1]>`
+    //~| expected slice, found array of 1 element
     assert_eq!(msg, 3);
 }
diff --git a/src/test/ui/issues/issue-15783.stderr b/src/test/ui/issues/issue-15783.stderr
index 595fe40..1d54b28 100644
--- a/src/test/ui/issues/issue-15783.stderr
+++ b/src/test/ui/issues/issue-15783.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-15783.rs:8:19
    |
 LL |     let msg = foo(x);
-   |                   ^ expected slice, found array of 1 elements
+   |                   ^ expected slice, found array of 1 element
    |
    = note: expected type `std::option::Option<&[&str]>`
               found type `std::option::Option<&[&str; 1]>`
diff --git a/src/test/ui/issues/issue-16250.rs b/src/test/ui/issues/issue-16250.rs
index bf01627..a3c6751 100644
--- a/src/test/ui/issues/issue-16250.rs
+++ b/src/test/ui/issues/issue-16250.rs
@@ -3,7 +3,7 @@
 pub struct Foo;
 
 extern {
-    pub fn foo(x: (Foo)); //~ ERROR unspecified layout
+    pub fn foo(x: (Foo)); //~ ERROR `extern` block uses type `Foo`
 }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-16250.stderr b/src/test/ui/issues/issue-16250.stderr
index f3686e8..5686ac3 100644
--- a/src/test/ui/issues/issue-16250.stderr
+++ b/src/test/ui/issues/issue-16250.stderr
@@ -1,8 +1,8 @@
-error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
+error: `extern` block uses type `Foo`, which is not FFI-safe
   --> $DIR/issue-16250.rs:6:20
    |
 LL |     pub fn foo(x: (Foo));
-   |                    ^^^
+   |                    ^^^ not FFI-safe
    |
 note: lint level defined here
   --> $DIR/issue-16250.rs:1:9
@@ -11,6 +11,7 @@
    |         ^^^^^^^^
    = note: `#[deny(improper_ctypes)]` implied by `#[deny(warnings)]`
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 note: type defined here
   --> $DIR/issue-16250.rs:3:1
    |
diff --git a/src/test/ui/issues/issue-17740.rs b/src/test/ui/issues/issue-17740.rs
index c131b89..b475684 100644
--- a/src/test/ui/issues/issue-17740.rs
+++ b/src/test/ui/issues/issue-17740.rs
@@ -4,11 +4,11 @@
 
 impl <'a> Foo<'a>{
     fn bar(self: &mut Foo) {
-    //~^ mismatched method receiver
+    //~^ mismatched `self` parameter type
     //~| expected type `Foo<'a>`
     //~| found type `Foo<'_>`
     //~| lifetime mismatch
-    //~| mismatched method receiver
+    //~| mismatched `self` parameter type
     //~| expected type `Foo<'a>`
     //~| found type `Foo<'_>`
     //~| lifetime mismatch
diff --git a/src/test/ui/issues/issue-17740.stderr b/src/test/ui/issues/issue-17740.stderr
index 7ab0fa4..b8a0a06 100644
--- a/src/test/ui/issues/issue-17740.stderr
+++ b/src/test/ui/issues/issue-17740.stderr
@@ -1,4 +1,4 @@
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/issue-17740.rs:6:18
    |
 LL |     fn bar(self: &mut Foo) {
@@ -23,7 +23,7 @@
 LL | impl <'a> Foo<'a>{
    |       ^^
 
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/issue-17740.rs:6:18
    |
 LL |     fn bar(self: &mut Foo) {
diff --git a/src/test/ui/issues/issue-17905-2.rs b/src/test/ui/issues/issue-17905-2.rs
index 259d945..44279cc 100644
--- a/src/test/ui/issues/issue-17905-2.rs
+++ b/src/test/ui/issues/issue-17905-2.rs
@@ -6,8 +6,8 @@
     isize
 > {
     fn say(self: &Pair<&str, isize>) {
-//~^ ERROR mismatched method receiver
-//~| ERROR mismatched method receiver
+//~^ ERROR mismatched `self` parameter type
+//~| ERROR mismatched `self` parameter type
         println!("{:?}", self);
     }
 }
diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr
index e3909e0..585bc9c 100644
--- a/src/test/ui/issues/issue-17905-2.stderr
+++ b/src/test/ui/issues/issue-17905-2.stderr
@@ -1,4 +1,4 @@
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/issue-17905-2.rs:8:18
    |
 LL |     fn say(self: &Pair<&str, isize>) {
@@ -21,7 +21,7 @@
 LL |     &str,
    |     ^
 
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/issue-17905-2.rs:8:18
    |
 LL |     fn say(self: &Pair<&str, isize>) {
diff --git a/src/test/ui/issues/issue-1871.stderr b/src/test/ui/issues/issue-1871.stderr
index fecd689..b774ca2 100644
--- a/src/test/ui/issues/issue-1871.stderr
+++ b/src/test/ui/issues/issue-1871.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-1871.rs:7:9
    |
 LL |       f.honk()
-   |         ^^^^
+   |         ^^^^ method not found in `{integer}`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr
index 63c33b7..d5e7092 100644
--- a/src/test/ui/issues/issue-18959.stderr
+++ b/src/test/ui/issues/issue-18959.stderr
@@ -1,10 +1,11 @@
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/issue-18959.rs:11:1
    |
+LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
+   |                    --- method `foo` has generic type parameters
+...
 LL | fn foo(b: &dyn Bar) {
    | ^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
-   |
-   = note: method `foo` has generic type parameters
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-1920-1.stderr b/src/test/ui/issues/issue-1920-1.stderr
index b3ac050..c62cbb0 100644
--- a/src/test/ui/issues/issue-1920-1.stderr
+++ b/src/test/ui/issues/issue-1920-1.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `foo::issue_1920::S: std::clone::Clone` is not satisfied
   --> $DIR/issue-1920-1.rs:12:5
    |
+LL | fn assert_clone<T>() where T : Clone { }
+   | ------------------------------------ required by `assert_clone`
+...
 LL |     assert_clone::<foo::issue_1920::S>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `foo::issue_1920::S`
-   |
-note: required by `assert_clone`
-  --> $DIR/issue-1920-1.rs:9:1
-   |
-LL | fn assert_clone<T>() where T : Clone { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-1920-2.stderr b/src/test/ui/issues/issue-1920-2.stderr
index a000a87..aad0762 100644
--- a/src/test/ui/issues/issue-1920-2.stderr
+++ b/src/test/ui/issues/issue-1920-2.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `bar::S: std::clone::Clone` is not satisfied
   --> $DIR/issue-1920-2.rs:10:5
    |
+LL | fn assert_clone<T>() where T : Clone { }
+   | ------------------------------------ required by `assert_clone`
+...
 LL |     assert_clone::<bar::S>();
    |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `bar::S`
-   |
-note: required by `assert_clone`
-  --> $DIR/issue-1920-2.rs:7:1
-   |
-LL | fn assert_clone<T>() where T : Clone { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-1920-3.stderr b/src/test/ui/issues/issue-1920-3.stderr
index 62e47a6..4378ea49 100644
--- a/src/test/ui/issues/issue-1920-3.stderr
+++ b/src/test/ui/issues/issue-1920-3.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `issue_1920::S: std::clone::Clone` is not satisfied
   --> $DIR/issue-1920-3.rs:14:5
    |
+LL | fn assert_clone<T>() where T : Clone { }
+   | ------------------------------------ required by `assert_clone`
+...
 LL |     assert_clone::<foo::issue_1920::S>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `issue_1920::S`
-   |
-note: required by `assert_clone`
-  --> $DIR/issue-1920-3.rs:11:1
-   |
-LL | fn assert_clone<T>() where T : Clone { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-19380.stderr b/src/test/ui/issues/issue-19380.stderr
index 27e3ff5..92bfdf1 100644
--- a/src/test/ui/issues/issue-19380.stderr
+++ b/src/test/ui/issues/issue-19380.stderr
@@ -1,10 +1,11 @@
 error[E0038]: the trait `Qiz` cannot be made into an object
   --> $DIR/issue-19380.rs:11:3
    |
+LL |   fn qiz();
+   |      --- associated function `qiz` has no `self` parameter
+...
 LL |   foos: &'static [&'static (dyn Qiz + 'static)]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
-   |
-   = note: method `qiz` has no receiver
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-19521.stderr b/src/test/ui/issues/issue-19521.stderr
index a43368b..c15c539 100644
--- a/src/test/ui/issues/issue-19521.stderr
+++ b/src/test/ui/issues/issue-19521.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-19521.rs:2:8
    |
 LL |     "".homura()();
-   |        ^^^^^^
+   |        ^^^^^^ method not found in `&'static str`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr
index e5da0a9..5415a45 100644
--- a/src/test/ui/issues/issue-19538.stderr
+++ b/src/test/ui/issues/issue-19538.stderr
@@ -1,18 +1,21 @@
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/issue-19538.rs:17:15
    |
+LL |     fn foo<T>(&self, val: T);
+   |        --- method `foo` has generic type parameters
+...
 LL |     let test: &mut dyn Bar = &mut thing;
    |               ^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
-   |
-   = note: method `foo` has generic type parameters
 
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/issue-19538.rs:17:30
    |
+LL |     fn foo<T>(&self, val: T);
+   |        --- method `foo` has generic type parameters
+...
 LL |     let test: &mut dyn Bar = &mut thing;
    |                              ^^^^^^^^^^ the trait `Bar` cannot be made into an object
    |
-   = note: method `foo` has generic type parameters
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-19692.stderr b/src/test/ui/issues/issue-19692.stderr
index 5e576f1..fe920c1 100644
--- a/src/test/ui/issues/issue-19692.stderr
+++ b/src/test/ui/issues/issue-19692.stderr
@@ -5,7 +5,7 @@
    | -------------- method `kaname` not found for this
 ...
 LL |     let Some(ref madoka) = Some(homura.kaname());
-   |                                        ^^^^^^
+   |                                        ^^^^^^ method not found in `Homura`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-19734.rs b/src/test/ui/issues/issue-19734.rs
index b730e19..fe4a327 100644
--- a/src/test/ui/issues/issue-19734.rs
+++ b/src/test/ui/issues/issue-19734.rs
@@ -4,5 +4,5 @@
 
 impl Type {
     undef!();
-    //~^ ERROR cannot find macro `undef!` in this scope
+    //~^ ERROR cannot find macro `undef` in this scope
 }
diff --git a/src/test/ui/issues/issue-19734.stderr b/src/test/ui/issues/issue-19734.stderr
index fc1a7d0..8175797 100644
--- a/src/test/ui/issues/issue-19734.stderr
+++ b/src/test/ui/issues/issue-19734.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `undef!` in this scope
+error: cannot find macro `undef` in this scope
   --> $DIR/issue-19734.rs:6:5
    |
 LL |     undef!();
diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr
index e271005..2754d6b 100644
--- a/src/test/ui/issues/issue-20005.stderr
+++ b/src/test/ui/issues/issue-20005.stderr
@@ -1,6 +1,9 @@
 error[E0277]: the size for values of type `Self` cannot be known at compilation time
   --> $DIR/issue-20005.rs:8:5
    |
+LL |   trait From<Src> {
+   |   --------------- required by `From`
+...
 LL | /     fn to<Dst>(
 LL | |         self
 LL | |     ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
@@ -11,11 +14,6 @@
    = help: the trait `std::marker::Sized` is not implemented for `Self`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where Self: std::marker::Sized` bound
-note: required by `From`
-  --> $DIR/issue-20005.rs:1:1
-   |
-LL | trait From<Src> {
-   | ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
index 762816c..72a8fe4 100644
--- a/src/test/ui/issues/issue-20413.stderr
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -9,6 +9,9 @@
 error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
   --> $DIR/issue-20413.rs:8:1
    |
+LL |   trait Foo {
+   |   --------- required by `Foo`
+...
 LL | / impl<T> Foo for T where NoData<T>: Foo {
 LL | |
 LL | |   fn answer(self) {
@@ -146,15 +149,13 @@
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<T>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<T>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
-note: required by `Foo`
-  --> $DIR/issue-20413.rs:1:1
-   |
-LL | trait Foo {
-   | ^^^^^^^^^
 
 error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
   --> $DIR/issue-20413.rs:10:3
    |
+LL |   trait Foo {
+   |   --------- required by `Foo`
+...
 LL | /   fn answer(self) {
 LL | |
 LL | |     let val: NoData<T> = NoData;
@@ -289,11 +290,6 @@
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<T>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<T>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
-note: required by `Foo`
-  --> $DIR/issue-20413.rs:1:1
-   |
-LL | trait Foo {
-   | ^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-2149.stderr b/src/test/ui/issues/issue-2149.stderr
index 1df32aa..8ce2ba0 100644
--- a/src/test/ui/issues/issue-2149.stderr
+++ b/src/test/ui/issues/issue-2149.stderr
@@ -10,7 +10,7 @@
   --> $DIR/issue-2149.rs:13:12
    |
 LL |     ["hi"].bind(|x| [x] );
-   |            ^^^^
+   |            ^^^^ method not found in `[&str; 1]`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `bind`, perhaps you need to implement it:
diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr
index 8e4e09b..4e5cace 100644
--- a/src/test/ui/issues/issue-21596.stderr
+++ b/src/test/ui/issues/issue-21596.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-21596.rs:4:22
    |
 LL |     println!("{}", z.to_string());
-   |                      ^^^^^^^^^
+   |                      ^^^^^^^^^ method not found in `*const u8`
    |
    = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref
    = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior
diff --git a/src/test/ui/issues/issue-21763.stderr b/src/test/ui/issues/issue-21763.stderr
index 87c048f..99d004a 100644
--- a/src/test/ui/issues/issue-21763.stderr
+++ b/src/test/ui/issues/issue-21763.stderr
@@ -1,6 +1,9 @@
 error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
   --> $DIR/issue-21763.rs:9:5
    |
+LL | fn foo<T: Send>() {}
+   | ----------------- required by `foo`
+...
 LL |     foo::<HashMap<Rc<()>, Rc<()>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
    |
@@ -9,11 +12,6 @@
    = note: required because of the requirements on the impl of `std::marker::Send` for `hashbrown::raw::RawTable<(std::rc::Rc<()>, std::rc::Rc<()>)>`
    = note: required because it appears within the type `hashbrown::map::HashMap<std::rc::Rc<()>, std::rc::Rc<()>, std::collections::hash_map::RandomState>`
    = note: required because it appears within the type `std::collections::HashMap<std::rc::Rc<()>, std::rc::Rc<()>>`
-note: required by `foo`
-  --> $DIR/issue-21763.rs:6:1
-   |
-LL | fn foo<T: Send>() {}
-   | ^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-21837.stderr b/src/test/ui/issues/issue-21837.stderr
index 3111d3a..20d02a9 100644
--- a/src/test/ui/issues/issue-21837.stderr
+++ b/src/test/ui/issues/issue-21837.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `T: Bound` is not satisfied
   --> $DIR/issue-21837.rs:8:9
    |
+LL | pub struct Foo<T: Bound>(T);
+   | ---------------------------- required by `Foo`
+...
 LL | impl<T> Trait2 for Foo<T> {}
    |         ^^^^^^ the trait `Bound` is not implemented for `T`
    |
    = help: consider adding a `where T: Bound` bound
-note: required by `Foo`
-  --> $DIR/issue-21837.rs:2:1
-   |
-LL | pub struct Foo<T: Bound>(T);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr
index 85e59d7..a6cce78 100644
--- a/src/test/ui/issues/issue-21974.stderr
+++ b/src/test/ui/issues/issue-21974.stderr
@@ -1,6 +1,9 @@
 error[E0283]: type annotations required: cannot resolve `&'a T: Foo`
   --> $DIR/issue-21974.rs:10:1
    |
+LL |   trait Foo {
+   |   --------- required by `Foo`
+...
 LL | / fn foo<'a,'b,T>(x: &'a T, y: &'b T)
 LL | |     where &'a T : Foo,
 LL | |           &'b T : Foo
@@ -9,12 +12,6 @@
 LL | |     y.foo();
 LL | | }
    | |_^
-   |
-note: required by `Foo`
-  --> $DIR/issue-21974.rs:6:1
-   |
-LL | trait Foo {
-   | ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr
index 8e04c0d..eb9aada 100644
--- a/src/test/ui/issues/issue-24204.stderr
+++ b/src/test/ui/issues/issue-24204.stderr
@@ -1,16 +1,14 @@
 error[E0271]: type mismatch resolving `<<T as Trait>::A as MultiDispatch<i32>>::O == T`
   --> $DIR/issue-24204.rs:14:1
    |
+LL | trait Trait: Sized {
+   | ------------------ required by `Trait`
+...
 LL | fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::new(b) }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found type parameter
    |
    = note: expected type `<<T as Trait>::A as MultiDispatch<i32>>::O`
               found type `T`
-note: required by `Trait`
-  --> $DIR/issue-24204.rs:7:1
-   |
-LL | trait Trait: Sized {
-   | ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-24267-flow-exit.rs b/src/test/ui/issues/issue-24267-flow-exit.rs
index a1b4d75..d6809ee 100644
--- a/src/test/ui/issues/issue-24267-flow-exit.rs
+++ b/src/test/ui/issues/issue-24267-flow-exit.rs
@@ -9,11 +9,11 @@
 pub fn foo1() {
     let x: i32;
     loop { x = break; }
-    println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x`
+    println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x`
 }
 
 pub fn foo2() {
     let x: i32;
     for _ in 0..10 { x = continue; }
-    println!("{}", x); //~ ERROR borrow of possibly uninitialized variable: `x`
+    println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x`
 }
diff --git a/src/test/ui/issues/issue-24267-flow-exit.stderr b/src/test/ui/issues/issue-24267-flow-exit.stderr
index 3b4f276..4eb41ca 100644
--- a/src/test/ui/issues/issue-24267-flow-exit.stderr
+++ b/src/test/ui/issues/issue-24267-flow-exit.stderr
@@ -1,14 +1,14 @@
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/issue-24267-flow-exit.rs:12:20
    |
 LL |     println!("{}", x);
-   |                    ^ use of possibly uninitialized `x`
+   |                    ^ use of possibly-uninitialized `x`
 
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/issue-24267-flow-exit.rs:18:20
    |
 LL |     println!("{}", x);
-   |                    ^ use of possibly uninitialized `x`
+   |                    ^ use of possibly-uninitialized `x`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr
index 4c6ac01..7ff019a 100644
--- a/src/test/ui/issues/issue-24424.stderr
+++ b/src/test/ui/issues/issue-24424.stderr
@@ -1,14 +1,11 @@
 error[E0283]: type annotations required: cannot resolve `T0: Trait0<'l0>`
   --> $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> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: required by `Trait0`
-  --> $DIR/issue-24424.rs:2:1
-   |
-LL | trait Trait0<'l0>  {}
-   | ^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs
index 48362d0..7253d35 100644
--- a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs
+++ b/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs
@@ -5,8 +5,6 @@
 // See further discussion on rust-lang/rust#24535,
 // rust-lang/rfcs#1006, and rust-lang/rfcs#107
 
-#![feature(bind_by_move_pattern_guards)]
-
 fn main() {
     rust_issue_24535();
     rfcs_issue_1006_1();
diff --git a/src/test/ui/issues/issue-25076.stderr b/src/test/ui/issues/issue-25076.stderr
index 435ab13..b583a6b 100644
--- a/src/test/ui/issues/issue-25076.stderr
+++ b/src/test/ui/issues/issue-25076.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `(): InOut<_>` is not satisfied
   --> $DIR/issue-25076.rs:10:5
    |
+LL | fn do_fold<B, F: InOut<B, Out=B>>(init: B, f: F) {}
+   | ------------------------------------------------ required by `do_fold`
+...
 LL |     do_fold(bot(), ());
    |     ^^^^^^^ the trait `InOut<_>` is not implemented for `()`
-   |
-note: required by `do_fold`
-  --> $DIR/issue-25076.rs:5:1
-   |
-LL | fn do_fold<B, F: InOut<B, Out=B>>(init: B, f: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-25385.stderr b/src/test/ui/issues/issue-25385.stderr
index e170a9d..ab4db7e 100644
--- a/src/test/ui/issues/issue-25385.stderr
+++ b/src/test/ui/issues/issue-25385.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-25385.rs:2:23
    |
 LL |     ($e:expr) => { $e.foo() }
-   |                       ^^^
+   |                       ^^^ method not found in `i32`
 ...
 LL |     foo!(a);
    |     -------- in this macro invocation
@@ -11,7 +11,7 @@
   --> $DIR/issue-25385.rs:10:15
    |
 LL |     foo!(1i32.foo());
-   |               ^^^
+   |               ^^^ method not found in `i32`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-26448-2.rs b/src/test/ui/issues/issue-26448-2.rs
index 17e7c1f..c60e06c 100644
--- a/src/test/ui/issues/issue-26448-2.rs
+++ b/src/test/ui/issues/issue-26448-2.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 pub struct Bar<T> {
     items: Vec<&'static str>,
diff --git a/src/test/ui/issues/issue-26448-3.rs b/src/test/ui/issues/issue-26448-3.rs
index e57352e..d48022c 100644
--- a/src/test/ui/issues/issue-26448-3.rs
+++ b/src/test/ui/issues/issue-26448-3.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 pub struct Item {
     _inner: &'static str,
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
index 1ffb7f6..82d8b9e 100644
--- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
+++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
@@ -5,8 +5,6 @@
 // reject it. But I want to make sure that we continue to reject it
 // (under NLL) even when that conservaive check goes away.
 
-#![feature(bind_by_move_pattern_guards)]
-
 fn main() {
     let mut b = &mut true;
     match b {
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
index a8eb78b..f0264b5 100644
--- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
+++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
@@ -1,5 +1,5 @@
 error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard
-  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:14:25
+  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:12:25
    |
 LL |         ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
    |                         ^^                   - mutable borrow occurs due to use of `r` in closure
diff --git a/src/test/ui/issues/issue-27697.rs b/src/test/ui/issues/issue-27697.rs
index 8307001..12af8a8 100644
--- a/src/test/ui/issues/issue-27697.rs
+++ b/src/test/ui/issues/issue-27697.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 use std::ops::Deref;
 
diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr
index 4c1dfb8..c9ede03 100644
--- a/src/test/ui/issues/issue-2823.stderr
+++ b/src/test/ui/issues/issue-2823.stderr
@@ -5,7 +5,7 @@
    | -------- method `clone` not found for this
 ...
 LL |     let _d = c.clone();
-   |                ^^^^^
+   |                ^^^^^ method not found in `C`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
diff --git a/src/test/ui/issues/issue-29124.stderr b/src/test/ui/issues/issue-29124.stderr
index 3beb728..c537c61 100644
--- a/src/test/ui/issues/issue-29124.stderr
+++ b/src/test/ui/issues/issue-29124.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-29124.rs:15:15
    |
 LL |     Obj::func.x();
-   |               ^
+   |               ^ method not found in `fn() -> Ret {Obj::func}`
    |
    = note: Obj::func is a function, perhaps you wish to call it
 
@@ -10,7 +10,7 @@
   --> $DIR/issue-29124.rs:17:10
    |
 LL |     func.x();
-   |          ^
+   |          ^ method not found in `fn() -> Ret {func}`
    |
    = note: func is a function, perhaps you wish to call it
 
diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr
index 3b42186..0dc9b0c 100644
--- a/src/test/ui/issues/issue-29147.stderr
+++ b/src/test/ui/issues/issue-29147.stderr
@@ -1,14 +1,11 @@
 error[E0283]: type annotations required: cannot resolve `S5<_>: Foo`
   --> $DIR/issue-29147.rs:21:13
    |
+LL | trait Foo { fn xxx(&self); }
+   |             -------------- required by `Foo::xxx`
+...
 LL |     let _ = <S5<_>>::xxx;
    |             ^^^^^^^^^^^^
-   |
-note: required by `Foo::xxx`
-  --> $DIR/issue-29147.rs:10:13
-   |
-LL | trait Foo { fn xxx(&self); }
-   |             ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-29181.stderr b/src/test/ui/issues/issue-29181.stderr
index 0920142..250b158 100644
--- a/src/test/ui/issues/issue-29181.stderr
+++ b/src/test/ui/issues/issue-29181.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-29181.rs:6:7
    |
 LL |     0.homura();
-   |       ^^^^^^
+   |       ^^^^^^ method not found in `{integer}`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr
index 3ca8338..6d03b78 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -11,7 +11,7 @@
   --> $DIR/issue-31173.rs:14:10
    |
 LL |         .collect();
-   |          ^^^^^^^
+   |          ^^^^^^^ method not found in `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>`
    |
    = note: the method `collect` exists but the following trait bounds were not satisfied:
            `&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`
diff --git a/src/test/ui/issues/issue-31561.rs b/src/test/ui/issues/issue-31561.rs
index 87b19fe5..813b240 100644
--- a/src/test/ui/issues/issue-31561.rs
+++ b/src/test/ui/issues/issue-31561.rs
@@ -6,5 +6,5 @@
 
 fn main() {
     let Thing::Foo(y) = Thing::Foo(1);
-    //~^ ERROR refutable pattern in local binding: `Bar` not covered
+    //~^ ERROR refutable pattern in local binding: `Bar` and `Baz` not covered
 }
diff --git a/src/test/ui/issues/issue-31561.stderr b/src/test/ui/issues/issue-31561.stderr
index 246137a..9ec26b0 100644
--- a/src/test/ui/issues/issue-31561.stderr
+++ b/src/test/ui/issues/issue-31561.stderr
@@ -1,15 +1,17 @@
-error[E0005]: refutable pattern in local binding: `Bar` not covered
+error[E0005]: refutable pattern in local binding: `Bar` and `Baz` not covered
   --> $DIR/issue-31561.rs:8:9
    |
 LL | / enum Thing {
 LL | |     Foo(u8),
 LL | |     Bar,
+   | |     --- not covered
 LL | |     Baz
+   | |     --- not covered
 LL | | }
    | |_- `Thing` defined here
 ...
 LL |       let Thing::Foo(y) = Thing::Foo(1);
-   |           ^^^^^^^^^^^^^ pattern `Bar` not covered
+   |           ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-32655.rs b/src/test/ui/issues/issue-32655.rs
index fad7bf5..f52e092 100644
--- a/src/test/ui/issues/issue-32655.rs
+++ b/src/test/ui/issues/issue-32655.rs
@@ -1,6 +1,6 @@
 macro_rules! foo (
     () => (
-        #[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope
+        #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope
         struct T;
     );
 );
@@ -12,7 +12,7 @@
 foo!();
 
 bar!(
-    #[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope
+    #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope
     struct S;
 );
 
diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr
index e13bed0..ca085b2 100644
--- a/src/test/ui/issues/issue-32655.stderr
+++ b/src/test/ui/issues/issue-32655.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `derive_Clone` in this scope
+error: cannot find attribute `derive_Clone` in this scope
   --> $DIR/issue-32655.rs:3:11
    |
 LL |         #[derive_Clone]
@@ -7,7 +7,7 @@
 LL | foo!();
    | ------- in this macro invocation
 
-error: cannot find attribute macro `derive_Clone` in this scope
+error: cannot find attribute `derive_Clone` in this scope
   --> $DIR/issue-32655.rs:15:7
    |
 LL |     #[derive_Clone]
diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr
index a31a74a..2960f4e 100644
--- a/src/test/ui/issues/issue-32963.stderr
+++ b/src/test/ui/issues/issue-32963.stderr
@@ -12,14 +12,11 @@
 error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied
   --> $DIR/issue-32963.rs:8:5
    |
+LL | fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
+   | ------------------------------------------ required by `size_of_copy`
+...
 LL |     size_of_copy::<dyn Misc + Copy>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn Misc`
-   |
-note: required by `size_of_copy`
-  --> $DIR/issue-32963.rs:5:1
-   |
-LL | fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index 7f89caf..8d52e08 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -45,7 +45,7 @@
   --> $DIR/issue-34334.rs:9:36
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-   |                                    ^^^^
+   |                                    ^^^^ method not found in `()`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr
index 99d99db..b381203 100644
--- a/src/test/ui/issues/issue-35677.stderr
+++ b/src/test/ui/issues/issue-35677.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-35677.rs:4:10
    |
 LL |     this.is_subset(other)
-   |          ^^^^^^^^^
+   |          ^^^^^^^^^ method not found in `&std::collections::HashSet<T>`
    |
    = note: the method `is_subset` exists but the following trait bounds were not satisfied:
            `T : std::cmp::Eq`
diff --git a/src/test/ui/issues/issue-36836.rs b/src/test/ui/issues/issue-36836.rs
new file mode 100644
index 0000000..99c5621
--- /dev/null
+++ b/src/test/ui/issues/issue-36836.rs
@@ -0,0 +1,15 @@
+// Previously, in addition to the real cause of the problem as seen below,
+// the compiler would tell the user:
+//
+// ```
+// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or
+// predicates
+// ```
+//
+// With this test, we check that only the relevant error is emitted.
+
+trait Foo {}
+
+impl<T> Foo for Bar<T> {} //~ ERROR cannot find type `Bar` in this scope
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-36836.stderr b/src/test/ui/issues/issue-36836.stderr
new file mode 100644
index 0000000..418194f
--- /dev/null
+++ b/src/test/ui/issues/issue-36836.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Bar` in this scope
+  --> $DIR/issue-36836.rs:13:17
+   |
+LL | impl<T> Foo for Bar<T> {}
+   |                 ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-38591.rs b/src/test/ui/issues/issue-38591.rs
index 7aa71f8..2f594b4 100644
--- a/src/test/ui/issues/issue-38591.rs
+++ b/src/test/ui/issues/issue-38591.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 struct S<T> {
     t : T,
diff --git a/src/test/ui/issues/issue-39175.stderr b/src/test/ui/issues/issue-39175.stderr
index 108c969..66680b9 100644
--- a/src/test/ui/issues/issue-39175.stderr
+++ b/src/test/ui/issues/issue-39175.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-39175.rs:15:39
    |
 LL |     Command::new("echo").arg("hello").exec();
-   |                                       ^^^^
+   |                                       ^^^^ method not found in `&mut std::process::Command`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr
index e4f1587..f15f771 100644
--- a/src/test/ui/issues/issue-39970.stderr
+++ b/src/test/ui/issues/issue-39970.stderr
@@ -1,17 +1,15 @@
 error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
   --> $DIR/issue-39970.rs:19:5
    |
+LL |     fn visit() {}
+   |     ---------- required by `Visit::visit`
+...
 LL |     <() as Visit>::visit();
    |     ^^^^^^^^^^^^^^^^^^^^ expected &(), found ()
    |
    = note: expected type `&()`
               found type `()`
    = note: required because of the requirements on the impl of `Visit` for `()`
-note: required by `Visit::visit`
-  --> $DIR/issue-39970.rs:6:5
-   |
-LL |     fn visit() {}
-   |     ^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-40827.stderr b/src/test/ui/issues/issue-40827.stderr
index 96b411b..9131120 100644
--- a/src/test/ui/issues/issue-40827.stderr
+++ b/src/test/ui/issues/issue-40827.stderr
@@ -1,6 +1,9 @@
 error[E0277]: `std::rc::Rc<Foo>` cannot be sent between threads safely
   --> $DIR/issue-40827.rs:14:5
    |
+LL | fn f<T: Send>(_: T) {}
+   | ------------------- required by `f`
+...
 LL |     f(Foo(Arc::new(Bar::B(None))));
    |     ^ `std::rc::Rc<Foo>` cannot be sent between threads safely
    |
@@ -8,15 +11,13 @@
    = note: required because it appears within the type `Bar`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<Bar>`
    = note: required because it appears within the type `Foo`
-note: required by `f`
-  --> $DIR/issue-40827.rs:11:1
-   |
-LL | fn f<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::rc::Rc<Foo>` cannot be shared between threads safely
   --> $DIR/issue-40827.rs:14:5
    |
+LL | fn f<T: Send>(_: T) {}
+   | ------------------- required by `f`
+...
 LL |     f(Foo(Arc::new(Bar::B(None))));
    |     ^ `std::rc::Rc<Foo>` cannot be shared between threads safely
    |
@@ -24,11 +25,6 @@
    = note: required because it appears within the type `Bar`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<Bar>`
    = note: required because it appears within the type `Foo`
-note: required by `f`
-  --> $DIR/issue-40827.rs:11:1
-   |
-LL | fn f<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-40845.rs b/src/test/ui/issues/issue-40845.rs
index c9102f4..a4ede6a 100644
--- a/src/test/ui/issues/issue-40845.rs
+++ b/src/test/ui/issues/issue-40845.rs
@@ -1,6 +1,6 @@
-trait T { m!(); } //~ ERROR cannot find macro `m!` in this scope
+trait T { m!(); } //~ ERROR cannot find macro `m` in this scope
 
 struct S;
-impl S { m!(); } //~ ERROR cannot find macro `m!` in this scope
+impl S { m!(); } //~ ERROR cannot find macro `m` in this scope
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-40845.stderr b/src/test/ui/issues/issue-40845.stderr
index a8be38e..2744330 100644
--- a/src/test/ui/issues/issue-40845.stderr
+++ b/src/test/ui/issues/issue-40845.stderr
@@ -1,10 +1,10 @@
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
   --> $DIR/issue-40845.rs:4:10
    |
 LL | impl S { m!(); }
    |          ^
 
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
   --> $DIR/issue-40845.rs:1:11
    |
 LL | trait T { m!(); }
diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr
index 359a234..0e1d55c 100644
--- a/src/test/ui/issues/issue-41880.stderr
+++ b/src/test/ui/issues/issue-41880.stderr
@@ -5,7 +5,7 @@
    | ------------------------ method `iter` not found for this
 ...
 LL |     println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
-   |                        ^^^^
+   |                        ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr
index e364650..33c3f18 100644
--- a/src/test/ui/issues/issue-43189.stderr
+++ b/src/test/ui/issues/issue-43189.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-43189.rs:10:8
    |
 LL |     ().a();
-   |        ^
+   |        ^ method not found in `()`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr
index b567410..d843629 100644
--- a/src/test/ui/issues/issue-43623.stderr
+++ b/src/test/ui/issues/issue-43623.stderr
@@ -1,41 +1,31 @@
 error[E0631]: type mismatch in function arguments
   --> $DIR/issue-43623.rs:14:5
    |
-LL |     break_me::<Type, fn(_)>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     expected signature of `for<'b> fn(<Type as Trait<'b>>::Assoc) -> _`
-   |     found signature of `fn(_) -> _`
-   |
-note: required by `break_me`
-  --> $DIR/issue-43623.rs:11:1
-   |
 LL | / pub fn break_me<T, F>(f: F)
 LL | | where T: for<'b> Trait<'b>,
 LL | |       F: for<'b> FnMut(<T as Trait<'b>>::Assoc) {
 LL | |     break_me::<Type, fn(_)>;
+   | |     ^^^^^^^^^^^^^^^^^^^^^^^
+   | |     |
+   | |     expected signature of `for<'b> fn(<Type as Trait<'b>>::Assoc) -> _`
+   | |     found signature of `fn(_) -> _`
 LL | |
 LL | |
 LL | | }
-   | |_^
+   | |_- required by `break_me`
 
 error[E0271]: type mismatch resolving `for<'b> <fn(_) as std::ops::FnOnce<(<Type as Trait<'b>>::Assoc,)>>::Output == ()`
   --> $DIR/issue-43623.rs:14:5
    |
-LL |     break_me::<Type, fn(_)>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime
-   |
-note: required by `break_me`
-  --> $DIR/issue-43623.rs:11:1
-   |
 LL | / pub fn break_me<T, F>(f: F)
 LL | | where T: for<'b> Trait<'b>,
 LL | |       F: for<'b> FnMut(<T as Trait<'b>>::Assoc) {
 LL | |     break_me::<Type, fn(_)>;
+   | |     ^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime
 LL | |
 LL | |
 LL | | }
-   | |_^
+   | |_- required by `break_me`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-43806.rs b/src/test/ui/issues/issue-43806.rs
index cbfbfa3..8c8cccf 100644
--- a/src/test/ui/issues/issue-43806.rs
+++ b/src/test/ui/issues/issue-43806.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 #![deny(unused_results)]
 
diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr
deleted file mode 100644
index 8008e53..0000000
--- a/src/test/ui/issues/issue-44415.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0`
-  --> $DIR/issue-44415.rs:6:17
-   |
-LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-   |                 ^^^^^^
-   |
-note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
-  --> $DIR/issue-44415.rs:6:17
-   |
-LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-   |                 ^^^^^^
-note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
-  --> $DIR/issue-44415.rs:6:26
-   |
-LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing layout of `Foo`...
-   = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
-   = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
-note: cycle used when processing `Foo`
-  --> $DIR/issue-44415.rs:5:1
-   |
-LL | struct Foo {
-   | ^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-46101.rs b/src/test/ui/issues/issue-46101.rs
index 2d9111e..8b1343b 100644
--- a/src/test/ui/issues/issue-46101.rs
+++ b/src/test/ui/issues/issue-46101.rs
@@ -2,3 +2,5 @@
 trait Foo {}
 #[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro
 struct S;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-46101.stderr b/src/test/ui/issues/issue-46101.stderr
index 772d4bf..9c88d3b 100644
--- a/src/test/ui/issues/issue-46101.stderr
+++ b/src/test/ui/issues/issue-46101.stderr
@@ -4,11 +4,6 @@
 LL | #[derive(Foo::Anything)]
    |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
 
-error[E0601]: `main` function not found in crate `issue_46101`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-46101.rs`
+error: aborting due to previous error
 
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0433, E0601.
-For more information about an error, try `rustc --explain E0433`.
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/issues/issue-47706.stderr b/src/test/ui/issues/issue-47706.stderr
index fa2e00c..c47eebb 100644
--- a/src/test/ui/issues/issue-47706.stderr
+++ b/src/test/ui/issues/issue-47706.stderr
@@ -10,21 +10,18 @@
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/issue-47706.rs:27:5
    |
-LL |     Bar(i32),
-   |     -------- takes 1 argument
+LL |       Bar(i32),
+   |       -------- takes 1 argument
 ...
-LL |     foo(Qux::Bar);
-   |     ^^^ expected function that takes 0 arguments
-   |
-note: required by `foo`
-  --> $DIR/issue-47706.rs:20:1
-   |
 LL | / fn foo<F>(f: F)
 LL | | where
 LL | |     F: Fn(),
 LL | | {
 LL | | }
-   | |_^
+   | |_- required by `foo`
+...
+LL |       foo(Qux::Bar);
+   |       ^^^ expected function that takes 0 arguments
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-48132.rs b/src/test/ui/issues/issue-48132.rs
index ea325ea..f564aef 100644
--- a/src/test/ui/issues/issue-48132.rs
+++ b/src/test/ui/issues/issue-48132.rs
@@ -3,6 +3,8 @@
 
 // run-pass
 
+#![allow(dead_code)]
+
 struct Inner<I, V> {
     iterator: I,
     item: V,
diff --git a/src/test/ui/issues/issue-48179.rs b/src/test/ui/issues/issue-48179.rs
index 90e9858..f81203d 100644
--- a/src/test/ui/issues/issue-48179.rs
+++ b/src/test/ui/issues/issue-48179.rs
@@ -1,7 +1,7 @@
 // Regression test for #48132. This was failing due to problems around
 // the projection caching and dropck type enumeration.
 
-// run-pass
+// check-pass
 
 pub struct Container<T: Iterator> {
     value: Option<T::Item>,
diff --git a/src/test/ui/issues/issue-49040.rs b/src/test/ui/issues/issue-49040.rs
index a5f05d2..b7a541d 100644
--- a/src/test/ui/issues/issue-49040.rs
+++ b/src/test/ui/issues/issue-49040.rs
@@ -1,2 +1,3 @@
 #![allow(unused_variables)]; //~ ERROR expected item, found `;`
+//~^ ERROR `main` function
 fn foo() {}
diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/issues/issue-49040.stderr
index de78b8d..4134d6a 100644
--- a/src/test/ui/issues/issue-49040.stderr
+++ b/src/test/ui/issues/issue-49040.stderr
@@ -5,8 +5,12 @@
    |                            ^ help: remove this semicolon
 
 error[E0601]: `main` function not found in crate `issue_49040`
+  --> $DIR/issue-49040.rs:1:1
    |
-   = note: consider adding a `main` function to `$DIR/issue-49040.rs`
+LL | / #![allow(unused_variables)];
+LL | |
+LL | | fn foo() {}
+   | |__^ consider adding a `main` function to `$DIR/issue-49040.rs`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-49074.rs b/src/test/ui/issues/issue-49074.rs
index 38074d5..752bb34 100644
--- a/src/test/ui/issues/issue-49074.rs
+++ b/src/test/ui/issues/issue-49074.rs
@@ -1,7 +1,7 @@
 // Check that unknown attribute error is shown even if there are unresolved macros.
 
 #[marco_use] // typo
-//~^ ERROR cannot find attribute macro `marco_use` in this scope
+//~^ ERROR cannot find attribute `marco_use` in this scope
 mod foo {
     macro_rules! bar {
         () => ();
@@ -9,5 +9,5 @@
 }
 
 fn main() {
-   bar!(); //~ ERROR cannot find macro `bar!` in this scope
+   bar!(); //~ ERROR cannot find macro `bar` in this scope
 }
diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr
index e0d3bb3..bbfeb4e 100644
--- a/src/test/ui/issues/issue-49074.stderr
+++ b/src/test/ui/issues/issue-49074.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `bar!` in this scope
+error: cannot find macro `bar` in this scope
   --> $DIR/issue-49074.rs:12:4
    |
 LL |    bar!();
@@ -6,7 +6,7 @@
    |
    = help: have you added the `#[macro_use]` on the module/import?
 
-error: cannot find attribute macro `marco_use` in this scope
+error: cannot find attribute `marco_use` in this scope
   --> $DIR/issue-49074.rs:3:3
    |
 LL | #[marco_use] // typo
diff --git a/src/test/ui/issues/issue-49934-errors.rs b/src/test/ui/issues/issue-49934-errors.rs
new file mode 100644
index 0000000..6fa5f01
--- /dev/null
+++ b/src/test/ui/issues/issue-49934-errors.rs
@@ -0,0 +1,13 @@
+fn foo<#[derive(Debug)] T>() {
+//~^ ERROR `derive` may only be applied to structs, enums and unions
+//~| ERROR expected an inert attribute, found a derive macro
+    match 0 {
+        #[derive(Debug)]
+        //~^ ERROR `derive` may only be applied to structs, enums and unions
+        //~| ERROR expected an inert attribute, found a derive macro
+        _ => (),
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/issues/issue-49934-errors.stderr b/src/test/ui/issues/issue-49934-errors.stderr
new file mode 100644
index 0000000..8778d88
--- /dev/null
+++ b/src/test/ui/issues/issue-49934-errors.stderr
@@ -0,0 +1,26 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-49934-errors.rs:1:8
+   |
+LL | fn foo<#[derive(Debug)] T>() {
+   |        ^^^^^^^^^^^^^^^^
+
+error: expected an inert attribute, found a derive macro
+  --> $DIR/issue-49934-errors.rs:1:17
+   |
+LL | fn foo<#[derive(Debug)] T>() {
+   |                 ^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-49934-errors.rs:5:9
+   |
+LL |         #[derive(Debug)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: expected an inert attribute, found a derive macro
+  --> $DIR/issue-49934-errors.rs:5:18
+   |
+LL |         #[derive(Debug)]
+   |                  ^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-49934.rs b/src/test/ui/issues/issue-49934.rs
index e75381a..262f493 100644
--- a/src/test/ui/issues/issue-49934.rs
+++ b/src/test/ui/issues/issue-49934.rs
@@ -1,15 +1,8 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(stmt_expr_attributes)]
 #![warn(unused_attributes)] //~ NOTE lint level defined here
 
-fn foo<#[derive(Debug)] T>() { //~ WARN unused attribute
-    match 0 {
-        #[derive(Debug)] //~ WARN unused attribute
-        _ => (),
-    }
-}
-
 fn main() {
     // fold_stmt (Item)
     #[allow(dead_code)]
diff --git a/src/test/ui/issues/issue-49934.stderr b/src/test/ui/issues/issue-49934.stderr
index 6ca751a..dbec379e3 100644
--- a/src/test/ui/issues/issue-49934.stderr
+++ b/src/test/ui/issues/issue-49934.stderr
@@ -1,5 +1,5 @@
 warning: `#[derive]` does nothing on macro invocations
-  --> $DIR/issue-49934.rs:20:5
+  --> $DIR/issue-49934.rs:13:5
    |
 LL |     #[derive(Debug)]
    |     ^^^^^^^^^^^^^^^^
@@ -7,10 +7,10 @@
    = note: this may become a hard error in a future release
 
 warning: unused attribute
-  --> $DIR/issue-49934.rs:6:8
+  --> $DIR/issue-49934.rs:19:5
    |
-LL | fn foo<#[derive(Debug)] T>() {
-   |        ^^^^^^^^^^^^^^^^
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/issue-49934.rs:4:9
@@ -19,31 +19,19 @@
    |         ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-49934.rs:8:9
-   |
-LL |         #[derive(Debug)]
-   |         ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-49934.rs:26:5
+  --> $DIR/issue-49934.rs:23:5
    |
 LL |     #[derive(Debug)]
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-49934.rs:30:5
-   |
-LL |     #[derive(Debug)]
-   |     ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-49934.rs:34:13
+  --> $DIR/issue-49934.rs:27:13
    |
 LL |     let _ = #[derive(Debug)] "Hello, world!";
    |             ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-49934.rs:39:9
+  --> $DIR/issue-49934.rs:32:9
    |
 LL |         #[derive(Debug)]
    |         ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
index 2c3a18b..29fd15f 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
@@ -2,7 +2,7 @@
   --> $DIR/option-as_deref_mut.rs:4:33
    |
 LL |     let _result = &mut Some(42).as_deref_mut();
-   |                                 ^^^^^^^^^^^^
+   |                                 ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>`
    |
    = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied:
            `{integer} : std::ops::DerefMut`
diff --git a/src/test/ui/issues/issue-50577.rs b/src/test/ui/issues/issue-50577.rs
index bf892a8..f0f1dc6 100644
--- a/src/test/ui/issues/issue-50577.rs
+++ b/src/test/ui/issues/issue-50577.rs
@@ -2,6 +2,5 @@
     enum Foo {
         Drop = assert_eq!(1, 1)
         //~^ ERROR if may be missing an else clause
-        //~| ERROR mismatched types [E0308]
     }
 }
diff --git a/src/test/ui/issues/issue-50577.stderr b/src/test/ui/issues/issue-50577.stderr
index 413c8c5..0c3ba2e 100644
--- a/src/test/ui/issues/issue-50577.stderr
+++ b/src/test/ui/issues/issue-50577.stderr
@@ -1,13 +1,3 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-50577.rs:3:16
-   |
-LL |         Drop = assert_eq!(1, 1)
-   |                ^^^^^^^^^^^^^^^^ expected isize, found ()
-   |
-   = note: expected type `isize`
-              found type `()`
-   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
-
 error[E0317]: if may be missing an else clause
   --> $DIR/issue-50577.rs:3:16
    |
@@ -23,7 +13,6 @@
    = help: consider adding an `else` block that evaluates to the expected type
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0317.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0317`.
diff --git a/src/test/ui/issues/issue-50781.stderr b/src/test/ui/issues/issue-50781.stderr
index c98f78c..02475ea 100644
--- a/src/test/ui/issues/issue-50781.stderr
+++ b/src/test/ui/issues/issue-50781.stderr
@@ -1,8 +1,8 @@
 error: the trait `X` cannot be made into an object
-  --> $DIR/issue-50781.rs:6:5
+  --> $DIR/issue-50781.rs:6:8
    |
 LL |     fn foo(&self) where Self: Trait;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |        ^^^
    |
 note: lint level defined here
   --> $DIR/issue-50781.rs:1:9
diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr
index 97214fb..5034e6d 100644
--- a/src/test/ui/issues/issue-5153.stderr
+++ b/src/test/ui/issues/issue-5153.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-5153.rs:10:27
    |
 LL |     (&5isize as &dyn Foo).foo();
-   |                           ^^^
+   |                           ^^^ method not found in `&dyn Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `foo`, perhaps you need to implement it:
diff --git a/src/test/ui/issues/issue-54062.stderr b/src/test/ui/issues/issue-54062.stderr
index 082ac91..3830ad4 100644
--- a/src/test/ui/issues/issue-54062.stderr
+++ b/src/test/ui/issues/issue-54062.stderr
@@ -8,7 +8,7 @@
   --> $DIR/issue-54062.rs:10:37
    |
 LL |     let _ = test.comps.inner.lock().unwrap();
-   |                                     ^^^^^^
+   |                                     ^^^^^^ method not found in `std::sys_common::mutex::MutexGuard<'_>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr
index 9863761..3ed2779 100644
--- a/src/test/ui/issues/issue-54302-cases.stderr
+++ b/src/test/ui/issues/issue-54302-cases.stderr
@@ -1,38 +1,58 @@
 error: implementation of `Foo` is not general enough
   --> $DIR/issue-54302-cases.rs:63:5
    |
-LL |     <u32 as RefFoo<u32>>::ref_foo(a)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | |     fn foo(self) -> &'x T;
+LL | | }
+   | |_- trait `Foo` defined here
+...
+LL |       <u32 as RefFoo<u32>>::ref_foo(a)
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`
-   = note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
+   = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
+   = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
 
 error: implementation of `Foo` is not general enough
   --> $DIR/issue-54302-cases.rs:69:5
    |
-LL |     <i32 as RefFoo<i32>>::ref_foo(a)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | |     fn foo(self) -> &'x T;
+LL | | }
+   | |_- trait `Foo` defined here
+...
+LL |       <i32 as RefFoo<i32>>::ref_foo(a)
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`
-   = note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
+   = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`...
+   = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
 
 error: implementation of `Foo` is not general enough
   --> $DIR/issue-54302-cases.rs:75:5
    |
-LL |     <u64 as RefFoo<u64>>::ref_foo(a)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | |     fn foo(self) -> &'x T;
+LL | | }
+   | |_- trait `Foo` defined here
+...
+LL |       <u64 as RefFoo<u64>>::ref_foo(a)
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`
-   = note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
+   = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`...
+   = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
 
 error: implementation of `Foo` is not general enough
   --> $DIR/issue-54302-cases.rs:81:5
    |
-LL |     <i64 as RefFoo<i64>>::ref_foo(a)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | |     fn foo(self) -> &'x T;
+LL | | }
+   | |_- trait `Foo` defined here
+...
+LL |       <i64 as RefFoo<i64>>::ref_foo(a)
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`
-   = note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
+   = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`...
+   = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr
index c6d0805..1b3f57b 100644
--- a/src/test/ui/issues/issue-54302.stderr
+++ b/src/test/ui/issues/issue-54302.stderr
@@ -1,11 +1,14 @@
 error: implementation of `Deserialize` is not general enough
   --> $DIR/issue-54302.rs:13:5
    |
+LL | trait Deserialize<'de> {}
+   | ------------------------- trait `Deserialize` defined here
+...
 LL |     assert_deserialize_owned::<&'static str>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
    |
-   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
-   = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
+   = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
+   = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-55731.stderr b/src/test/ui/issues/issue-55731.stderr
index f25e18e..f44c842 100644
--- a/src/test/ui/issues/issue-55731.stderr
+++ b/src/test/ui/issues/issue-55731.stderr
@@ -1,11 +1,16 @@
 error: implementation of `DistributedIteratorMulti` is not general enough
   --> $DIR/issue-55731.rs:48:5
    |
-LL |     multi(Map {
-   |     ^^^^^
+LL | / trait DistributedIteratorMulti<Source> {
+LL | |     type Item;
+LL | | }
+   | |_- trait `DistributedIteratorMulti` defined here
+...
+LL |       multi(Map {
+   |       ^^^^^ implementation of `DistributedIteratorMulti` is not general enough
    |
-   = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`
-   = note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
+   = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`...
+   = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-56806.rs b/src/test/ui/issues/issue-56806.rs
index b6454e5..b1dac26 100644
--- a/src/test/ui/issues/issue-56806.rs
+++ b/src/test/ui/issues/issue-56806.rs
@@ -1,7 +1,6 @@
 pub trait Trait {
     fn dyn_instead_of_self(self: Box<dyn Trait>);
-    //~^ ERROR invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)>
+    //~^ ERROR invalid `self` parameter type
 }
 
-pub fn main() {
-}
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-56806.stderr b/src/test/ui/issues/issue-56806.stderr
index fae6a26..a4f9aad 100644
--- a/src/test/ui/issues/issue-56806.stderr
+++ b/src/test/ui/issues/issue-56806.stderr
@@ -1,11 +1,12 @@
-error[E0307]: invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)>
+error[E0307]: invalid `self` parameter type: std::boxed::Box<(dyn Trait + 'static)>
   --> $DIR/issue-56806.rs:2:34
    |
 LL |     fn dyn_instead_of_self(self: Box<dyn Trait>);
    |                                  ^^^^^^^^^^^^^^
    |
-   = note: type must be `Self` or a type that dereferences to it
+   = note: type of `self` must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0307`.
diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr
index 1d2ff76..c4000c8 100644
--- a/src/test/ui/issues/issue-57362-1.stderr
+++ b/src/test/ui/issues/issue-57362-1.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-57362-1.rs:20:7
    |
 LL |     a.f();
-   |       ^
+   |       ^ method not found in `fn(&u8)`
    |
    = note: a is a function, perhaps you wish to call it
    = help: items from traits can only be used if the trait is implemented and in scope
diff --git a/src/test/ui/issues/issue-60057.rs b/src/test/ui/issues/issue-60057.rs
index 3027d01..b52343a 100644
--- a/src/test/ui/issues/issue-60057.rs
+++ b/src/test/ui/issues/issue-60057.rs
@@ -15,3 +15,5 @@
         }
     }
 }
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-60057.stderr b/src/test/ui/issues/issue-60057.stderr
index 6b96720..4d915fc 100644
--- a/src/test/ui/issues/issue-60057.stderr
+++ b/src/test/ui/issues/issue-60057.stderr
@@ -10,11 +10,6 @@
 LL |             banana: banana
    |                     ^^^^^^ help: you might have meant to use the available field: `self.banana`
 
-error[E0601]: `main` function not found in crate `issue_60057`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-60057.rs`
+error: aborting due to 2 previous errors
 
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0425, E0601.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr
index a79b195..a977ba3 100644
--- a/src/test/ui/issues/issue-60283.stderr
+++ b/src/test/ui/issues/issue-60283.stderr
@@ -1,33 +1,27 @@
 error[E0631]: type mismatch in function arguments
   --> $DIR/issue-60283.rs:14:5
    |
-LL |     foo((), drop)
-   |     ^^^
-   |     |
-   |     expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
-   |     found signature of `fn(_) -> _`
-   |
-note: required by `foo`
-  --> $DIR/issue-60283.rs:9:1
-   |
 LL | / pub fn foo<T, F>(_: T, _: F)
 LL | | where T: for<'a> Trait<'a>,
 LL | |       F: for<'a> FnMut(<T as Trait<'a>>::Item) {}
-   | |_________________________________________________^
+   | |_________________________________________________- required by `foo`
+...
+LL |       foo((), drop)
+   |       ^^^
+   |       |
+   |       expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
+   |       found signature of `fn(_) -> _`
 
 error[E0271]: type mismatch resolving `for<'a> <fn(_) {std::mem::drop::<_>} as std::ops::FnOnce<(<() as Trait<'a>>::Item,)>>::Output == ()`
   --> $DIR/issue-60283.rs:14:5
    |
-LL |     foo((), drop)
-   |     ^^^ expected bound lifetime parameter 'a, found concrete lifetime
-   |
-note: required by `foo`
-  --> $DIR/issue-60283.rs:9:1
-   |
 LL | / pub fn foo<T, F>(_: T, _: F)
 LL | | where T: for<'a> Trait<'a>,
 LL | |       F: for<'a> FnMut(<T as Trait<'a>>::Item) {}
-   | |_________________________________________________^
+   | |_________________________________________________- required by `foo`
+...
+LL |       foo((), drop)
+   |       ^^^ expected bound lifetime parameter 'a, found concrete lifetime
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs b/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs
index 8fc09c8..de7d6a0 100644
--- a/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs
+++ b/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs
@@ -5,7 +5,7 @@
 // aux-build:xcrate-issue-61711-b.rs
 // compile-flags:--extern xcrate_issue_61711_b
 
-// run-pass
+// build-pass
 
 fn f<F: Fn(xcrate_issue_61711_b::Struct)>(_: F) { }
 fn main() { }
diff --git a/src/test/ui/issues/issue-64430.rs b/src/test/ui/issues/issue-64430.rs
new file mode 100644
index 0000000..0bc66e0
--- /dev/null
+++ b/src/test/ui/issues/issue-64430.rs
@@ -0,0 +1,14 @@
+// compile-flags:-C panic=abort
+
+#![no_std]
+pub struct Foo;
+
+fn main() {
+    Foo.bar()
+    //~^ ERROR E0599
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop{}
+}
diff --git a/src/test/ui/issues/issue-64430.stderr b/src/test/ui/issues/issue-64430.stderr
new file mode 100644
index 0000000..f1b2de8
--- /dev/null
+++ b/src/test/ui/issues/issue-64430.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `bar` found for type `Foo` in the current scope
+  --> $DIR/issue-64430.rs:7:9
+   |
+LL | pub struct Foo;
+   | --------------- method `bar` not found for this
+...
+LL |     Foo.bar()
+   |         ^^^ method not found in `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-6919.rs b/src/test/ui/issues/issue-6919.rs
index 11aed12..6f1e1f9 100644
--- a/src/test/ui/issues/issue-6919.rs
+++ b/src/test/ui/issues/issue-6919.rs
@@ -4,7 +4,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![crate_id="issue-6919"]
 extern crate issue6919_3;
 
 pub fn main() {
diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs
index 611d280..4637814 100644
--- a/src/test/ui/issues/issue-8460-const.rs
+++ b/src/test/ui/issues/issue-8460-const.rs
@@ -1,3 +1,5 @@
+// compile-flags: -O
+
 #![deny(const_err)]
 
 use std::{isize, i8, i16, i32, i64};
diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr
index 31b1da4..7e5a22e 100644
--- a/src/test/ui/issues/issue-8460-const.stderr
+++ b/src/test/ui/issues/issue-8460-const.stderr
@@ -1,245 +1,245 @@
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:7:36
+  --> $DIR/issue-8460-const.rs:9:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/issue-8460-const.rs:1:9
+  --> $DIR/issue-8460-const.rs:3:9
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:7:36
+  --> $DIR/issue-8460-const.rs:9:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:10:36
+  --> $DIR/issue-8460-const.rs:12:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:10:36
+  --> $DIR/issue-8460-const.rs:12:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:13:36
+  --> $DIR/issue-8460-const.rs:15:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:13:36
+  --> $DIR/issue-8460-const.rs:15:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:16:36
+  --> $DIR/issue-8460-const.rs:18:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:16:36
+  --> $DIR/issue-8460-const.rs:18:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:19:36
+  --> $DIR/issue-8460-const.rs:21:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:19:36
+  --> $DIR/issue-8460-const.rs:21:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
 
 error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:22:36
+  --> $DIR/issue-8460-const.rs:24:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:22:36
+  --> $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:25:36
+  --> $DIR/issue-8460-const.rs:27:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
    |                                    ^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:25:36
+  --> $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:28:36
+  --> $DIR/issue-8460-const.rs:30:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:28:36
+  --> $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:31:36
+  --> $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:31:36
+  --> $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:34:36
+  --> $DIR/issue-8460-const.rs:36:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
    |                                    ^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:34:36
+  --> $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:37:36
+  --> $DIR/issue-8460-const.rs:39:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:37:36
+  --> $DIR/issue-8460-const.rs:39:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:40:36
+  --> $DIR/issue-8460-const.rs:42:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:40:36
+  --> $DIR/issue-8460-const.rs:42:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:43:36
+  --> $DIR/issue-8460-const.rs:45:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:43:36
+  --> $DIR/issue-8460-const.rs:45:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:46:36
+  --> $DIR/issue-8460-const.rs:48:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:46:36
+  --> $DIR/issue-8460-const.rs:48:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:49:36
+  --> $DIR/issue-8460-const.rs:51:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:49:36
+  --> $DIR/issue-8460-const.rs:51:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
    |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
 
 error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:52:36
+  --> $DIR/issue-8460-const.rs:54:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
    |                                    ^^^^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:52:36
+  --> $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:55:36
+  --> $DIR/issue-8460-const.rs:57:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
    |                                    ^^^^^^^
 
 error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:55:36
+  --> $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:58:36
+  --> $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:58:36
+  --> $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:61:36
+  --> $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:61:36
+  --> $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:64:36
+  --> $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:64:36
+  --> $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
diff --git a/src/test/ui/issues/issue-8460-const2.rs b/src/test/ui/issues/issue-8460-const2.rs
new file mode 100644
index 0000000..c3f53e3
--- /dev/null
+++ b/src/test/ui/issues/issue-8460-const2.rs
@@ -0,0 +1,59 @@
+// compile-flags: -C overflow-checks=on -O
+
+#![deny(const_err)]
+
+use std::{isize, i8, i16, i32, i64};
+use std::thread;
+
+fn main() {
+    assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+    //~^ ERROR attempt to divide with overflow
+    assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+    //~^ ERROR attempt to divide with overflow
+    assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+    //~^ ERROR attempt to divide with overflow
+    assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+    //~^ ERROR attempt to divide with overflow
+    assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+    //~^ 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());
+    //~^ ERROR attempt to calculate the remainder with overflow
+    assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with overflow
+    assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+    //~^ ERROR attempt to calculate the remainder with overflow
+    assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+    //~^ 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
new file mode 100644
index 0000000..b688ec1
--- /dev/null
+++ b/src/test/ui/issues/issue-8460-const2.stderr
@@ -0,0 +1,188 @@
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const2.rs:9:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-8460-const2.rs:3:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const2.rs:11:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^
+
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const2.rs:13:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^
+
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const2.rs:15:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^
+
+error: attempt to divide with overflow
+  --> $DIR/issue-8460-const2.rs:17:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^
+
+error: attempt to divide by zero
+  --> $DIR/issue-8460-const2.rs:19:36
+   |
+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
+   |
+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
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+   |                                    ^^^^^^^^
+
+error: this expression will panic at runtime
+  --> $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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+   |                                    ^^^^^^^
+
+error: this expression will panic at runtime
+  --> $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
+
diff --git a/src/test/ui/iterators/bound.stderr b/src/test/ui/iterators/bound.stderr
index 1405738..92a91ff 100644
--- a/src/test/ui/iterators/bound.stderr
+++ b/src/test/ui/iterators/bound.stderr
@@ -1,16 +1,13 @@
 error[E0277]: `u8` is not an iterator
   --> $DIR/bound.rs:2:10
    |
+LL | struct S<I: Iterator>(I);
+   | ------------------------- required by `S`
 LL | struct T(S<u8>);
    |          ^^^^^ `u8` is not an iterator
    |
    = help: the trait `std::iter::Iterator` is not implemented for `u8`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-note: required by `S`
-  --> $DIR/bound.rs:1:1
-   |
-LL | struct S<I: Iterator>(I);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr
index dffbdb7..0a1fb56 100644
--- a/src/test/ui/json-short.stderr
+++ b/src/test/ui/json-short.stderr
@@ -11,9 +11,9 @@
 
 If you don't know the basics of Rust, you can go look to the Rust Book to get
 started: https://doc.rust-lang.org/book/
-"},"level":"error","spans":[],"children":[{"message":"consider adding a `main` function to `$DIR/json-short.rs`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0601]: `main` function not found in crate `json_short`
+"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":76,"byte_end":76,"line_start":2,"line_end":2,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:2:63: error[E0601]: `main` function not found in crate `json_short`
 "}
 {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
 "}
-{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`.
+{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`.
 "}
diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr
index 929a807..1fe5946 100644
--- a/src/test/ui/kindck/kindck-copy.stderr
+++ b/src/test/ui/kindck/kindck-copy.stderr
@@ -1,138 +1,107 @@
 error[E0277]: the trait bound `&'static mut isize: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:27:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<&'static mut isize>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'static mut isize`
    |
    = help: the following implementations were found:
              <isize as std::marker::Copy>
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `&'a mut isize: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:28:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<&'a mut isize>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut isize`
    |
    = help: the following implementations were found:
              <isize as std::marker::Copy>
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::boxed::Box<isize>: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:31:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<Box<isize>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<isize>`
-   |
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:32:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<String>();
    |     ^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
-   |
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::vec::Vec<isize>: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:33:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<Vec<isize> >();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::vec::Vec<isize>`
-   |
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::boxed::Box<&'a mut isize>: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:34:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<Box<&'a mut isize>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<&'a mut isize>`
-   |
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::boxed::Box<dyn Dummy>: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:42:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<Box<dyn Dummy>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<dyn Dummy>`
-   |
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::boxed::Box<dyn Dummy + std::marker::Send>: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:43:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<Box<dyn Dummy + Send>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<dyn Dummy + std::marker::Send>`
-   |
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `&'a mut (dyn Dummy + std::marker::Send + 'a): std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:46:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<&'a mut (dyn Dummy + Send)>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut (dyn Dummy + std::marker::Send + 'a)`
-   |
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `MyNoncopyStruct: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:64:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<MyNoncopyStruct>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `MyNoncopyStruct`
-   |
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::rc::Rc<isize>: std::marker::Copy` is not satisfied
   --> $DIR/kindck-copy.rs:67:5
    |
+LL | fn assert_copy<T:Copy>() { }
+   | ------------------------ required by `assert_copy`
+...
 LL |     assert_copy::<Rc<isize>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc<isize>`
-   |
-note: required by `assert_copy`
-  --> $DIR/kindck-copy.rs:5:1
-   |
-LL | fn assert_copy<T:Copy>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.stderr b/src/test/ui/kindck/kindck-impl-type-params-2.stderr
index bd971c9..6d59942 100644
--- a/src/test/ui/kindck/kindck-impl-type-params-2.stderr
+++ b/src/test/ui/kindck/kindck-impl-type-params-2.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied
   --> $DIR/kindck-impl-type-params-2.rs:13:5
    |
+LL | fn take_param<T:Foo>(foo: &T) { }
+   | ----------------------------- required by `take_param`
+...
 LL |     take_param(&x);
    |     ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>`
    |
    = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>`
-note: required by `take_param`
-  --> $DIR/kindck-impl-type-params-2.rs:9:1
-   |
-LL | fn take_param<T:Foo>(foo: &T) { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr
index 1e719e2..a530631 100644
--- a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:18:5
    |
+LL | fn take_param<T:Foo>(foo: &T) { }
+   | ----------------------------- required by `take_param`
+...
 LL |     take_param(&x);
    |     ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>`
    |
    = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>`
-note: required by `take_param`
-  --> $DIR/kindck-inherited-copy-bound.rs:14:1
-   |
-LL | fn take_param<T:Foo>(foo: &T) { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/kindck-inherited-copy-bound.rs:24:19
diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr
index 2aacd27..6d60de8 100644
--- a/src/test/ui/kindck/kindck-nonsendable-1.stderr
+++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr
@@ -1,16 +1,14 @@
 error[E0277]: `std::rc::Rc<usize>` cannot be sent between threads safely
   --> $DIR/kindck-nonsendable-1.rs:9:5
    |
+LL | fn bar<F:FnOnce() + Send>(_: F) { }
+   | ------------------------------- required by `bar`
+...
 LL |     bar(move|| foo(x));
    |     ^^^ `std::rc::Rc<usize>` cannot be sent between threads safely
    |
    = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<usize>`
    = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22 x:std::rc::Rc<usize>]`
-note: required by `bar`
-  --> $DIR/kindck-nonsendable-1.rs:5:1
-   |
-LL | fn bar<F:FnOnce() + Send>(_: F) { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/kindck/kindck-send-object.stderr b/src/test/ui/kindck/kindck-send-object.stderr
index c9aadd8..3ca2d73 100644
--- a/src/test/ui/kindck/kindck-send-object.stderr
+++ b/src/test/ui/kindck/kindck-send-object.stderr
@@ -1,31 +1,27 @@
 error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
   --> $DIR/kindck-send-object.rs:12:5
    |
+LL | fn assert_send<T:Send>() { }
+   | ------------------------ required by `assert_send`
+...
 LL |     assert_send::<&'static (dyn Dummy + 'static)>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)`
-note: required by `assert_send`
-  --> $DIR/kindck-send-object.rs:5:1
-   |
-LL | fn assert_send<T:Send>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dyn Dummy` cannot be sent between threads safely
   --> $DIR/kindck-send-object.rs:17:5
    |
+LL | fn assert_send<T:Send>() { }
+   | ------------------------ required by `assert_send`
+...
 LL |     assert_send::<Box<dyn Dummy>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `dyn Dummy`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn Dummy>`
    = note: required because it appears within the type `std::boxed::Box<dyn Dummy>`
-note: required by `assert_send`
-  --> $DIR/kindck-send-object.rs:5:1
-   |
-LL | fn assert_send<T:Send>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/kindck/kindck-send-object1.nll.stderr b/src/test/ui/kindck/kindck-send-object1.nll.stderr
index 998dc90..c7d18cd 100644
--- a/src/test/ui/kindck/kindck-send-object1.nll.stderr
+++ b/src/test/ui/kindck/kindck-send-object1.nll.stderr
@@ -1,31 +1,27 @@
 error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely
   --> $DIR/kindck-send-object1.rs:10:5
    |
+LL | fn assert_send<T:Send+'static>() { }
+   | -------------------------------- required by `assert_send`
+...
 LL |     assert_send::<&'a dyn Dummy>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'a)`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn Dummy + 'a)`
-note: required by `assert_send`
-  --> $DIR/kindck-send-object1.rs:5:1
-   |
-LL | fn assert_send<T:Send+'static>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
   --> $DIR/kindck-send-object1.rs:29:5
    |
+LL | fn assert_send<T:Send+'static>() { }
+   | -------------------------------- required by `assert_send`
+...
 LL |     assert_send::<Box<dyn Dummy + 'a>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `(dyn Dummy + 'a)`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn Dummy + 'a)>`
    = note: required because it appears within the type `std::boxed::Box<(dyn Dummy + 'a)>`
-note: required by `assert_send`
-  --> $DIR/kindck-send-object1.rs:5:1
-   |
-LL | fn assert_send<T:Send+'static>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/kindck/kindck-send-object1.stderr b/src/test/ui/kindck/kindck-send-object1.stderr
index 757b41a..0f5f7e0 100644
--- a/src/test/ui/kindck/kindck-send-object1.stderr
+++ b/src/test/ui/kindck/kindck-send-object1.stderr
@@ -1,16 +1,14 @@
 error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely
   --> $DIR/kindck-send-object1.rs:10:5
    |
+LL | fn assert_send<T:Send+'static>() { }
+   | -------------------------------- required by `assert_send`
+...
 LL |     assert_send::<&'a dyn Dummy>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'a)`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn Dummy + 'a)`
-note: required by `assert_send`
-  --> $DIR/kindck-send-object1.rs:5:1
-   |
-LL | fn assert_send<T:Send+'static>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0477]: the type `&'a (dyn Dummy + std::marker::Sync + 'a)` does not fulfill the required lifetime
   --> $DIR/kindck-send-object1.rs:14:5
@@ -23,17 +21,15 @@
 error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
   --> $DIR/kindck-send-object1.rs:29:5
    |
+LL | fn assert_send<T:Send+'static>() { }
+   | -------------------------------- required by `assert_send`
+...
 LL |     assert_send::<Box<dyn Dummy + 'a>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `(dyn Dummy + 'a)`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn Dummy + 'a)>`
    = note: required because it appears within the type `std::boxed::Box<(dyn Dummy + 'a)>`
-note: required by `assert_send`
-  --> $DIR/kindck-send-object1.rs:5:1
-   |
-LL | fn assert_send<T:Send+'static>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/kindck/kindck-send-object2.stderr b/src/test/ui/kindck/kindck-send-object2.stderr
index c1c9db9..72cd985 100644
--- a/src/test/ui/kindck/kindck-send-object2.stderr
+++ b/src/test/ui/kindck/kindck-send-object2.stderr
@@ -1,31 +1,27 @@
 error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
   --> $DIR/kindck-send-object2.rs:7:5
    |
+LL | fn assert_send<T:Send>() { }
+   | ------------------------ required by `assert_send`
+...
 LL |     assert_send::<&'static dyn Dummy>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)`
-note: required by `assert_send`
-  --> $DIR/kindck-send-object2.rs:3:1
-   |
-LL | fn assert_send<T:Send>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dyn Dummy` cannot be sent between threads safely
   --> $DIR/kindck-send-object2.rs:12:5
    |
+LL | fn assert_send<T:Send>() { }
+   | ------------------------ required by `assert_send`
+...
 LL |     assert_send::<Box<dyn Dummy>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `dyn Dummy`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn Dummy>`
    = note: required because it appears within the type `std::boxed::Box<dyn Dummy>`
-note: required by `assert_send`
-  --> $DIR/kindck-send-object2.rs:3:1
-   |
-LL | fn assert_send<T:Send>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/kindck/kindck-send-owned.stderr b/src/test/ui/kindck/kindck-send-owned.stderr
index 75c757d..ee919f0 100644
--- a/src/test/ui/kindck/kindck-send-owned.stderr
+++ b/src/test/ui/kindck/kindck-send-owned.stderr
@@ -1,17 +1,15 @@
 error[E0277]: `*mut u8` cannot be sent between threads safely
   --> $DIR/kindck-send-owned.rs:12:5
    |
+LL | fn assert_send<T:Send>() { }
+   | ------------------------ required by `assert_send`
+...
 LL |     assert_send::<Box<*mut u8>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `*mut u8`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<*mut u8>`
    = note: required because it appears within the type `std::boxed::Box<*mut u8>`
-note: required by `assert_send`
-  --> $DIR/kindck-send-owned.rs:3:1
-   |
-LL | fn assert_send<T:Send>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/kindck/kindck-send-unsafe.stderr b/src/test/ui/kindck/kindck-send-unsafe.stderr
index 2fbb07a..a87e1c7 100644
--- a/src/test/ui/kindck/kindck-send-unsafe.stderr
+++ b/src/test/ui/kindck/kindck-send-unsafe.stderr
@@ -1,15 +1,13 @@
 error[E0277]: `*mut &'a isize` cannot be sent between threads safely
   --> $DIR/kindck-send-unsafe.rs:6:5
    |
+LL | fn assert_send<T:Send>() { }
+   | ------------------------ required by `assert_send`
+...
 LL |     assert_send::<*mut &'a isize>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut &'a isize` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `*mut &'a isize`
-note: required by `assert_send`
-  --> $DIR/kindck-send-unsafe.rs:3:1
-   |
-LL | fn assert_send<T:Send>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/lifetime-before-type-params.rs
index 9b905d4..5a71d6e 100644
--- a/src/test/ui/lifetime-before-type-params.rs
+++ b/src/test/ui/lifetime-before-type-params.rs
@@ -7,3 +7,5 @@
 //~^ ERROR lifetime parameters must be declared prior to type parameters
 fn fourth<'a, T, 'b, U, 'c, V>() {}
 //~^ ERROR lifetime parameters must be declared prior to type parameters
+
+fn main() {}
diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr
index ffc6784..76d7d0f 100644
--- a/src/test/ui/lifetime-before-type-params.stderr
+++ b/src/test/ui/lifetime-before-type-params.stderr
@@ -22,10 +22,5 @@
 LL | fn fourth<'a, T, 'b, U, 'c, V>() {}
    |          --------^^-----^^---- help: reorder the parameters: lifetimes, then types: `<'a, 'b, 'c, T, U, V>`
 
-error[E0601]: `main` function not found in crate `lifetime_before_type_params`
-   |
-   = note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs`
+error: aborting due to 4 previous errors
 
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
index 779e2eb..2ed4d6d 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
@@ -12,11 +12,11 @@
   --> $DIR/ex3-both-anon-regions-3.rs:2:5
    |
 LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
-   |                         -                    - let's call the lifetime of this reference `'1`
+   |                         -                    - let's call the lifetime of this reference `'3`
    |                         |
-   |                         let's call the lifetime of this reference `'2`
+   |                         let's call the lifetime of this reference `'4`
 LL |     z.push((x,y));
-   |     ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+   |     ^^^^^^^^^^^^^ argument requires that `'3` must outlive `'4`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lint/empty-lint-attributes.rs b/src/test/ui/lint/empty-lint-attributes.rs
index 1f0a953..9a0ec25 100644
--- a/src/test/ui/lint/empty-lint-attributes.rs
+++ b/src/test/ui/lint/empty-lint-attributes.rs
@@ -1,6 +1,6 @@
 #![feature(lint_reasons)]
 
-// run-pass
+// check-pass
 
 // Empty (and reason-only) lint attributes are legal—although we may want to
 // lint them in the future (Issue #55112).
diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
index eda9e2c..7dcbdd0 100644
--- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs
+++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
@@ -1,25 +1,77 @@
-// build-pass (FIXME(62277): could be check-pass?)
+#![feature(box_patterns, stmt_expr_attributes)]
+
+#![feature(or_patterns)]
+//~^ WARN the feature `or_patterns` is incomplete
 
 #![allow(ellipsis_inclusive_range_patterns)]
 #![allow(unreachable_patterns)]
 #![allow(unused_variables)]
-#![warn(unused_parens)]
+#![deny(unused_parens)]
+
+fn lint_on_top_level() {
+    let (a) = 0; //~ ERROR unnecessary parentheses around pattern
+    for (a) in 0..1 {} //~ ERROR unnecessary parentheses around pattern
+    if let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern
+    while let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern
+    fn foo((a): u8) {} //~ ERROR unnecessary parentheses around pattern
+    let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern
+}
+
+fn _no_lint_attr() {
+    let _x = #[allow(dead_code)] (1 + 2);
+}
+
+// Don't lint in these cases (#64106).
+fn or_patterns_no_lint() {
+    match Box::new(0) {
+        box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`.
+        _ => {}
+    }
+
+    match 0 {
+        x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`.
+        _ => {}
+    }
+
+    if let &(0 | 1) = &0 {} // Should also not lint.
+    if let &mut (0 | 1) = &mut 0 {} // Same.
+
+    fn foo((Ok(a) | Err(a)): Result<u8, u8>) {} // Doesn't parse if we remove parens for now.
+
+    let _ = |(Ok(a) | Err(a)): Result<u8, u8>| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or.
+}
+
+fn or_patterns_will_lint() {
+    if let (0 | 1) = 0 {} //~ ERROR unnecessary parentheses around pattern
+    if let ((0 | 1),) = (0,) {} //~ ERROR unnecessary parentheses around pattern
+    if let [(0 | 1)] = [0] {} //~ ERROR unnecessary parentheses around pattern
+    if let 0 | (1 | 2) = 0 {} //~ ERROR unnecessary parentheses around pattern
+    struct TS(u8);
+    if let TS((0 | 1)) = TS(0) {} //~ ERROR unnecessary parentheses around pattern
+    struct NS { f: u8 }
+    if let NS { f: (0 | 1) } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern
+}
+
+// Don't lint on `&(mut x)` because `&mut x` means something else (#55342).
+fn deref_mut_binding_no_lint() {
+    let &(mut x) = &0;
+}
 
 fn main() {
     match 1 {
-        (_) => {}         //~ WARNING: unnecessary parentheses around pattern
-        (y) => {}         //~ WARNING: unnecessary parentheses around pattern
-        (ref r) => {}     //~ WARNING: unnecessary parentheses around pattern
-        (e @ 1...2) => {} //~ WARNING: unnecessary parentheses around outer pattern
-        (1...2) => {}     // Non ambiguous range pattern should not warn
+        (_) => {} //~ ERROR unnecessary parentheses around pattern
+        (y) => {} //~ ERROR unnecessary parentheses around pattern
+        (ref r) => {} //~ ERROR unnecessary parentheses around pattern
+        (e @ 1...2) => {} //~ ERROR unnecessary parentheses around pattern
+        (1...2) => {} // Non ambiguous range pattern should not warn
         e @ (3...4) => {} // Non ambiguous range pattern should not warn
     }
 
     match &1 {
-        (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern
-        &(_) => {}           //~ WARNING: unnecessary parentheses around pattern
-        e @ &(1...2) => {}   // Ambiguous range pattern should not warn
-        &(1...2) => {}       // Ambiguous range pattern should not warn
+        (e @ &(1...2)) => {} //~ ERROR unnecessary parentheses around pattern
+        &(_) => {} //~ ERROR unnecessary parentheses around pattern
+        e @ &(1...2) => {} // Ambiguous range pattern should not warn
+        &(1...2) => {} // Ambiguous range pattern should not warn
     }
 
     match &1 {
@@ -28,19 +80,19 @@
     }
 
     match 1 {
-        (_) => {}         //~ WARNING: unnecessary parentheses around pattern
-        (y) => {}         //~ WARNING: unnecessary parentheses around pattern
-        (ref r) => {}     //~ WARNING: unnecessary parentheses around pattern
-        (e @ 1..=2) => {} //~ WARNING: unnecessary parentheses around outer pattern
-        (1..=2) => {}     // Non ambiguous range pattern should not warn
+        (_) => {} //~ ERROR unnecessary parentheses around pattern
+        (y) => {} //~ ERROR unnecessary parentheses around pattern
+        (ref r) => {} //~ ERROR unnecessary parentheses around pattern
+        (e @ 1..=2) => {} //~ ERROR unnecessary parentheses around pattern
+        (1..=2) => {} // Non ambiguous range pattern should not warn
         e @ (3..=4) => {} // Non ambiguous range pattern should not warn
     }
 
     match &1 {
-        (e @ &(1..=2)) => {} //~ WARNING: unnecessary parentheses around outer pattern
-        &(_) => {}           //~ WARNING: unnecessary parentheses around pattern
-        e @ &(1..=2) => {}   // Ambiguous range pattern should not warn
-        &(1..=2) => {}       // Ambiguous range pattern should not warn
+        (e @ &(1..=2)) => {} //~ ERROR unnecessary parentheses around pattern
+        &(_) => {} //~ ERROR unnecessary parentheses around pattern
+        e @ &(1..=2) => {} // Ambiguous range pattern should not warn
+        &(1..=2) => {} // Ambiguous range pattern should not warn
     }
 
     match &1 {
diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
index 3b31219..675dd4f 100644
--- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
+++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
@@ -1,78 +1,160 @@
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:10:9
+warning: the feature `or_patterns` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-54538-unused-parens-lint.rs:3:12
    |
-LL |         (_) => {}
+LL | #![feature(or_patterns)]
+   |            ^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:12:9
+   |
+LL |     let (a) = 0;
    |         ^^^ help: remove these parentheses
    |
 note: lint level defined here
-  --> $DIR/issue-54538-unused-parens-lint.rs:6:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:9:9
    |
-LL | #![warn(unused_parens)]
+LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:11:9
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:13:9
+   |
+LL |     for (a) in 0..1 {}
+   |         ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:14:12
+   |
+LL |     if let (a) = 0 {}
+   |            ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:15:15
+   |
+LL |     while let (a) = 0 {}
+   |               ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:16:12
+   |
+LL |     fn foo((a): u8) {}
+   |            ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:17:14
+   |
+LL |     let _ = |(a): u8| 0;
+   |              ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:45:12
+   |
+LL |     if let (0 | 1) = 0 {}
+   |            ^^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:46:13
+   |
+LL |     if let ((0 | 1),) = (0,) {}
+   |             ^^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:47:13
+   |
+LL |     if let [(0 | 1)] = [0] {}
+   |             ^^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:48:16
+   |
+LL |     if let 0 | (1 | 2) = 0 {}
+   |                ^^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:50:15
+   |
+LL |     if let TS((0 | 1)) = TS(0) {}
+   |               ^^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:52:20
+   |
+LL |     if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
+   |                    ^^^^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:62:9
+   |
+LL |         (_) => {}
+   |         ^^^ help: remove these parentheses
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:63:9
    |
 LL |         (y) => {}
    |         ^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:12:9
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:64:9
    |
 LL |         (ref r) => {}
    |         ^^^^^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:13:9
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:65:9
    |
 LL |         (e @ 1...2) => {}
    |         ^^^^^^^^^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:19:9
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:71:9
    |
 LL |         (e @ &(1...2)) => {}
    |         ^^^^^^^^^^^^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:20:10
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:72:10
    |
 LL |         &(_) => {}
    |          ^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:31:9
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:83:9
    |
 LL |         (_) => {}
    |         ^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:32:9
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:84:9
    |
 LL |         (y) => {}
    |         ^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:33:9
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:85:9
    |
 LL |         (ref r) => {}
    |         ^^^^^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:34:9
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:86:9
    |
 LL |         (e @ 1..=2) => {}
    |         ^^^^^^^^^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:40:9
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:92:9
    |
 LL |         (e @ &(1..=2)) => {}
    |         ^^^^^^^^^^^^^^ help: remove these parentheses
 
-warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:41:10
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:93:10
    |
 LL |         &(_) => {}
    |          ^^^ help: remove these parentheses
 
+error: aborting due to 24 previous errors
+
diff --git a/src/test/ui/lint/lint-ctypes-enum.rs b/src/test/ui/lint/lint-ctypes-enum.rs
index 45eefff..3898e67 100644
--- a/src/test/ui/lint/lint-ctypes-enum.rs
+++ b/src/test/ui/lint/lint-ctypes-enum.rs
@@ -1,4 +1,5 @@
 #![feature(transparent_enums, transparent_unions)]
+#![feature(ptr_internals)]
 #![deny(improper_ctypes)]
 #![allow(dead_code)]
 
@@ -35,35 +36,37 @@
 
 extern {
    fn zf(x: Z);
-   fn uf(x: U); //~ ERROR enum has no representation hint
-   fn bf(x: B); //~ ERROR enum has no representation hint
-   fn tf(x: T); //~ ERROR enum has no representation hint
+   fn uf(x: U); //~ ERROR `extern` block uses type `U`
+   fn bf(x: B); //~ ERROR `extern` block uses type `B`
+   fn tf(x: T); //~ ERROR `extern` block uses type `T`
    fn repr_c(x: ReprC);
    fn repr_u8(x: U8);
    fn repr_isize(x: Isize);
    fn option_ref(x: Option<&'static u8>);
    fn option_fn(x: Option<extern "C" fn()>);
    fn nonnull(x: Option<std::ptr::NonNull<u8>>);
+   fn unique(x: Option<std::ptr::Unique<u8>>);
+   //~^ ERROR `extern` block uses type `std::option::Option<std::ptr::Unique<u8>>`
    fn nonzero_u8(x: Option<num::NonZeroU8>);
    fn nonzero_u16(x: Option<num::NonZeroU16>);
    fn nonzero_u32(x: Option<num::NonZeroU32>);
    fn nonzero_u64(x: Option<num::NonZeroU64>);
    fn nonzero_u128(x: Option<num::NonZeroU128>);
-   //~^ ERROR 128-bit integers don't currently have a known stable ABI
+   //~^ ERROR `extern` block uses type `u128`
    fn nonzero_usize(x: Option<num::NonZeroUsize>);
    fn nonzero_i8(x: Option<num::NonZeroI8>);
    fn nonzero_i16(x: Option<num::NonZeroI16>);
    fn nonzero_i32(x: Option<num::NonZeroI32>);
    fn nonzero_i64(x: Option<num::NonZeroI64>);
    fn nonzero_i128(x: Option<num::NonZeroI128>);
-   //~^ ERROR 128-bit integers don't currently have a known stable ABI
+   //~^ ERROR `extern` block uses type `i128`
    fn nonzero_isize(x: Option<num::NonZeroIsize>);
    fn transparent_struct(x: Option<TransparentStruct<num::NonZeroU8>>);
    fn transparent_enum(x: Option<TransparentEnum<num::NonZeroU8>>);
    fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
-   //~^ ERROR enum has no representation hint
-   fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR enum has no representation hint
-   fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR enum has no representation hint
+   //~^ ERROR `extern` block uses type
+   fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR `extern` block uses type
+   fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR `extern` block uses type
 }
 
-pub fn main() { }
+pub fn main() {}
diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr
index 2a60cd1..81939e6 100644
--- a/src/test/ui/lint/lint-ctypes-enum.stderr
+++ b/src/test/ui/lint/lint-ctypes-enum.stderr
@@ -1,82 +1,101 @@
-error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:38:13
+error: `extern` block uses type `U`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:39:13
    |
 LL |    fn uf(x: U);
-   |             ^
+   |             ^ not FFI-safe
    |
 note: lint level defined here
-  --> $DIR/lint-ctypes-enum.rs:2:9
+  --> $DIR/lint-ctypes-enum.rs:3:9
    |
 LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
 note: type defined here
-  --> $DIR/lint-ctypes-enum.rs:8:1
+  --> $DIR/lint-ctypes-enum.rs:9:1
    |
 LL | enum U { A }
    | ^^^^^^^^^^^^
 
-error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:39:13
+error: `extern` block uses type `B`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:40:13
    |
 LL |    fn bf(x: B);
-   |             ^
+   |             ^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
 note: type defined here
-  --> $DIR/lint-ctypes-enum.rs:9:1
+  --> $DIR/lint-ctypes-enum.rs:10:1
    |
 LL | enum B { C, D }
    | ^^^^^^^^^^^^^^^
 
-error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:40:13
+error: `extern` block uses type `T`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:41:13
    |
 LL |    fn tf(x: T);
-   |             ^
+   |             ^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
 note: type defined here
-  --> $DIR/lint-ctypes-enum.rs:10:1
+  --> $DIR/lint-ctypes-enum.rs:11:1
    |
 LL | enum T { E, F, G }
    | ^^^^^^^^^^^^^^^^^^
 
-error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
-  --> $DIR/lint-ctypes-enum.rs:51:23
+error: `extern` block uses type `std::option::Option<std::ptr::Unique<u8>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:48:17
+   |
+LL |    fn unique(x: Option<std::ptr::Unique<u8>>);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
+error: `extern` block uses type `u128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:54:23
    |
 LL |    fn nonzero_u128(x: Option<num::NonZeroU128>);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
 
-error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
-  --> $DIR/lint-ctypes-enum.rs:58:23
+error: `extern` block uses type `i128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:61:23
    |
 LL |    fn nonzero_i128(x: Option<num::NonZeroI128>);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
 
-error: `extern` block uses type `std::option::Option<TransparentUnion<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:63:28
+error: `extern` block uses type `std::option::Option<TransparentUnion<std::num::NonZeroU8>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:66:28
    |
 LL |    fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
 
-error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:65:20
+error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:68:20
    |
 LL |    fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
 
-error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:66:20
+error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:69:20
    |
 LL |    fn no_result(x: Result<(), num::NonZeroI32>);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/lint/lint-ctypes.rs b/src/test/ui/lint/lint-ctypes.rs
index a3d9b6f..e20503a 100644
--- a/src/test/ui/lint/lint-ctypes.rs
+++ b/src/test/ui/lint/lint-ctypes.rs
@@ -1,7 +1,7 @@
-#![deny(improper_ctypes)]
 #![feature(rustc_private)]
 
 #![allow(private_in_public)]
+#![deny(improper_ctypes)]
 
 extern crate libc;
 
@@ -54,12 +54,13 @@
     pub fn trait_type(p: &dyn Clone); //~ ERROR uses type `dyn std::clone::Clone`
     pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
     pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
-    pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
-    pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData
+    pub fn zero_size(p: ZeroSize); //~ ERROR uses type `ZeroSize`
+    pub fn zero_size_phantom(p: ZeroSizeWithPhantomData);
+    //~^ ERROR uses type `ZeroSizeWithPhantomData`
     pub fn zero_size_phantom_toplevel()
-        -> ::std::marker::PhantomData<bool>; //~ ERROR: composed only of PhantomData
-    pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific
-    pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific
+        -> ::std::marker::PhantomData<bool>; //~ ERROR uses type `std::marker::PhantomData<bool>`
+    pub fn fn_type(p: RustFn); //~ ERROR uses type `fn()`
+    pub fn fn_type2(p: fn()); //~ ERROR uses type `fn()`
     pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box<u32>`
     pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
     pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
diff --git a/src/test/ui/lint/lint-ctypes.stderr b/src/test/ui/lint/lint-ctypes.stderr
index c78463b..e533a76 100644
--- a/src/test/ui/lint/lint-ctypes.stderr
+++ b/src/test/ui/lint/lint-ctypes.stderr
@@ -1,170 +1,201 @@
-error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
+error: `extern` block uses type `Foo`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:46:28
    |
 LL |     pub fn ptr_type1(size: *const Foo);
-   |                            ^^^^^^^^^^
+   |                            ^^^^^^^^^^ not FFI-safe
    |
 note: lint level defined here
-  --> $DIR/lint-ctypes.rs:1:9
+  --> $DIR/lint-ctypes.rs:4:9
    |
 LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 note: type defined here
   --> $DIR/lint-ctypes.rs:24:1
    |
 LL | pub struct Foo;
    | ^^^^^^^^^^^^^^^
 
-error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
+error: `extern` block uses type `Foo`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:47:28
    |
 LL |     pub fn ptr_type2(size: *const Foo);
-   |                            ^^^^^^^^^^
+   |                            ^^^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 note: type defined here
   --> $DIR/lint-ctypes.rs:24:1
    |
 LL | pub struct Foo;
    | ^^^^^^^^^^^^^^^
 
-error: `extern` block uses type `[u32]` which is not FFI-safe: slices have no C equivalent
+error: `extern` block uses type `[u32]`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:48:26
    |
 LL |     pub fn slice_type(p: &[u32]);
-   |                          ^^^^^^
+   |                          ^^^^^^ not FFI-safe
    |
    = help: consider using a raw pointer instead
+   = note: slices have no C equivalent
 
-error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
+error: `extern` block uses type `str`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:49:24
    |
 LL |     pub fn str_type(p: &str);
-   |                        ^^^^
+   |                        ^^^^ not FFI-safe
    |
    = help: consider using `*const u8` and a length instead
+   = note: string slices have no C equivalent
 
-error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
+error: `extern` block uses type `std::boxed::Box<u32>`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:50:24
    |
 LL |     pub fn box_type(p: Box<u32>);
-   |                        ^^^^^^^^
+   |                        ^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 
-error: `extern` block uses type `char` which is not FFI-safe: the `char` type has no C equivalent
+error: `extern` block uses type `char`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:51:25
    |
 LL |     pub fn char_type(p: char);
-   |                         ^^^^
+   |                         ^^^^ not FFI-safe
    |
    = help: consider using `u32` or `libc::wchar_t` instead
+   = note: the `char` type has no C equivalent
 
-error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
+error: `extern` block uses type `i128`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:52:25
    |
 LL |     pub fn i128_type(p: i128);
-   |                         ^^^^
+   |                         ^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
 
-error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
+error: `extern` block uses type `u128`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:53:25
    |
 LL |     pub fn u128_type(p: u128);
-   |                         ^^^^
+   |                         ^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
 
-error: `extern` block uses type `dyn std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
+error: `extern` block uses type `dyn std::clone::Clone`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:54:26
    |
 LL |     pub fn trait_type(p: &dyn Clone);
-   |                          ^^^^^^^^^^
+   |                          ^^^^^^^^^^ not FFI-safe
+   |
+   = note: trait objects have no C equivalent
 
-error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
+error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:55:26
    |
 LL |     pub fn tuple_type(p: (i32, i32));
-   |                          ^^^^^^^^^^
+   |                          ^^^^^^^^^^ not FFI-safe
    |
    = help: consider using a struct instead
+   = note: tuples have unspecified layout
 
-error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
+error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:56:27
    |
 LL |     pub fn tuple_type2(p: I32Pair);
-   |                           ^^^^^^^
+   |                           ^^^^^^^ not FFI-safe
    |
    = help: consider using a struct instead
+   = note: tuples have unspecified layout
 
-error: `extern` block uses type `ZeroSize` which is not FFI-safe: this struct has no fields
+error: `extern` block uses type `ZeroSize`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:57:25
    |
 LL |     pub fn zero_size(p: ZeroSize);
-   |                         ^^^^^^^^
+   |                         ^^^^^^^^ not FFI-safe
    |
    = help: consider adding a member to this struct
+   = note: this struct has no fields
 note: type defined here
   --> $DIR/lint-ctypes.rs:20:1
    |
 LL | pub struct ZeroSize;
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: `extern` block uses type `ZeroSizeWithPhantomData` which is not FFI-safe: composed only of PhantomData
+error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
   --> $DIR/lint-ctypes.rs:58:33
    |
 LL |     pub fn zero_size_phantom(p: ZeroSizeWithPhantomData);
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: composed only of `PhantomData`
+note: type defined here
+  --> $DIR/lint-ctypes.rs:43:1
+   |
+LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `extern` block uses type `std::marker::PhantomData<bool>` which is not FFI-safe: composed only of PhantomData
-  --> $DIR/lint-ctypes.rs:60:12
+error: `extern` block uses type `std::marker::PhantomData<bool>`, which is not FFI-safe
+  --> $DIR/lint-ctypes.rs:61:12
    |
 LL |         -> ::std::marker::PhantomData<bool>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: composed only of `PhantomData`
 
-error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
-  --> $DIR/lint-ctypes.rs:61:23
+error: `extern` block uses type `fn()`, which is not FFI-safe
+  --> $DIR/lint-ctypes.rs:62:23
    |
 LL |     pub fn fn_type(p: RustFn);
-   |                       ^^^^^^
+   |                       ^^^^^^ not FFI-safe
    |
    = help: consider using an `extern fn(...) -> ...` function pointer instead
+   = note: this function pointer has Rust-specific calling convention
 
-error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
-  --> $DIR/lint-ctypes.rs:62:24
+error: `extern` block uses type `fn()`, which is not FFI-safe
+  --> $DIR/lint-ctypes.rs:63:24
    |
 LL |     pub fn fn_type2(p: fn());
-   |                        ^^^^
+   |                        ^^^^ not FFI-safe
    |
    = help: consider using an `extern fn(...) -> ...` function pointer instead
+   = note: this function pointer has Rust-specific calling convention
 
-error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
-  --> $DIR/lint-ctypes.rs:63:28
+error: `extern` block uses type `std::boxed::Box<u32>`, which is not FFI-safe
+  --> $DIR/lint-ctypes.rs:64:28
    |
 LL |     pub fn fn_contained(p: RustBadRet);
-   |                            ^^^^^^^^^^
+   |                            ^^^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 
-error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
-  --> $DIR/lint-ctypes.rs:64:32
+error: `extern` block uses type `i128`, which is not FFI-safe
+  --> $DIR/lint-ctypes.rs:65:32
    |
 LL |     pub fn transparent_i128(p: TransparentI128);
-   |                                ^^^^^^^^^^^^^^^
+   |                                ^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
 
-error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
-  --> $DIR/lint-ctypes.rs:65:31
+error: `extern` block uses type `str`, which is not FFI-safe
+  --> $DIR/lint-ctypes.rs:66:31
    |
 LL |     pub fn transparent_str(p: TransparentStr);
-   |                               ^^^^^^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^ not FFI-safe
    |
    = help: consider using `*const u8` and a length instead
+   = note: string slices have no C equivalent
 
-error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
-  --> $DIR/lint-ctypes.rs:66:30
+error: `extern` block uses type `std::boxed::Box<u32>`, which is not FFI-safe
+  --> $DIR/lint-ctypes.rs:67:30
    |
 LL |     pub fn transparent_fn(p: TransparentBadFn);
-   |                              ^^^^^^^^^^^^^^^^
+   |                              ^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
 
 error: aborting due to 20 previous errors
 
diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
new file mode 100644
index 0000000..25d5f8e
--- /dev/null
+++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+
+#![deny(improper_ctypes)]
+
+type A = impl Fn();
+
+pub fn ret_closure() -> A {
+    || {}
+}
+
+extern "C" {
+    pub fn a(_: A);
+    //~^ ERROR `extern` block uses type `A`, which is not FFI-safe
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
new file mode 100644
index 0000000..136d564
--- /dev/null
+++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
@@ -0,0 +1,15 @@
+error: `extern` block uses type `A`, which is not FFI-safe
+  --> $DIR/opaque-ty-ffi-unsafe.rs:12:17
+   |
+LL |     pub fn a(_: A);
+   |                 ^ not FFI-safe
+   |
+note: lint level defined here
+  --> $DIR/opaque-ty-ffi-unsafe.rs:3:9
+   |
+LL | #![deny(improper_ctypes)]
+   |         ^^^^^^^^^^^^^^^
+   = note: opaque types have no C equivalent
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index c7c53ab..678c888 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -412,7 +412,7 @@
 {
   "message": "For more information about this error, try `rustc --explain E0412`.",
   "code": null,
-  "level": "",
+  "level": "failure-note",
   "spans": [],
   "children": [],
   "rendered": "\u001b[0m\u001b[1mFor more information about this error, try `rustc --explain E0412`.\u001b[0m
diff --git a/src/test/ui/loops/loop-proper-liveness.rs b/src/test/ui/loops/loop-proper-liveness.rs
index b8f76fb..b242ec4 100644
--- a/src/test/ui/loops/loop-proper-liveness.rs
+++ b/src/test/ui/loops/loop-proper-liveness.rs
@@ -6,7 +6,7 @@
     'a: loop {
         x = loop { break 'a };
     }
-    println!("{:?}", x); //~ ERROR borrow of possibly uninitialized variable
+    println!("{:?}", x); //~ ERROR borrow of possibly-uninitialized variable
 }
 
 // test2 and test3 should not fail.
diff --git a/src/test/ui/loops/loop-proper-liveness.stderr b/src/test/ui/loops/loop-proper-liveness.stderr
index c877206..d55f9ff 100644
--- a/src/test/ui/loops/loop-proper-liveness.stderr
+++ b/src/test/ui/loops/loop-proper-liveness.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `x`
+error[E0381]: borrow of possibly-uninitialized variable: `x`
   --> $DIR/loop-proper-liveness.rs:9:22
    |
 LL |     println!("{:?}", x);
-   |                      ^ use of possibly uninitialized `x`
+   |                      ^ use of possibly-uninitialized `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
index 015e05e..96054de 100644
--- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
@@ -2,7 +2,7 @@
   --> $DIR/macro-backtrace-invalid-internals.rs:5:13
    |
 LL |           1.fake()
-   |             ^^^^
+   |             ^^^^ method not found in `{integer}`
 ...
 LL |     fake_method_stmt!();
    |     -------------------- in this macro invocation
@@ -42,7 +42,7 @@
   --> $DIR/macro-backtrace-invalid-internals.rs:23:13
    |
 LL |           1.fake()
-   |             ^^^^
+   |             ^^^^ method not found in `{integer}`
 ...
 LL |     let _ = fake_method_expr!();
    |             ------------------- in this macro invocation
diff --git a/src/test/ui/macros/macro-expansion-tests.stderr b/src/test/ui/macros/macro-expansion-tests.stderr
index 4ad9ade..8b3f7ca 100644
--- a/src/test/ui/macros/macro-expansion-tests.stderr
+++ b/src/test/ui/macros/macro-expansion-tests.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
   --> $DIR/macro-expansion-tests.rs:7:21
    |
 LL |     fn g() -> i32 { m!() }
@@ -6,7 +6,7 @@
    |
    = help: have you added the `#[macro_use]` on the module/import?
 
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
   --> $DIR/macro-expansion-tests.rs:15:21
    |
 LL |     fn g() -> i32 { m!() }
diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr
index 967f4f3..ce2e198 100644
--- a/src/test/ui/macros/macro-name-typo.stderr
+++ b/src/test/ui/macros/macro-name-typo.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `printlx!` in this scope
+error: cannot find macro `printlx` in this scope
   --> $DIR/macro-name-typo.rs:2:5
    |
 LL |     printlx!("oh noes!");
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.rs b/src/test/ui/macros/macro-path-prelude-fail-3.rs
index 597053d..68eb350 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.rs
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.rs
@@ -1,3 +1,3 @@
 fn main() {
-    inline!(); //~ ERROR cannot find macro `inline!` in this scope
+    inline!(); //~ ERROR cannot find macro `inline` in this scope
 }
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
index 96b8a24..ec00760 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `inline!` in this scope
+error: cannot find macro `inline` in this scope
   --> $DIR/macro-path-prelude-fail-3.rs:2:5
    |
 LL |     inline!();
diff --git a/src/test/ui/macros/macro-reexport-removed.rs b/src/test/ui/macros/macro-reexport-removed.rs
index b69a1fa..874c94d 100644
--- a/src/test/ui/macros/macro-reexport-removed.rs
+++ b/src/test/ui/macros/macro-reexport-removed.rs
@@ -2,7 +2,7 @@
 
 #![feature(macro_reexport)] //~ ERROR feature has been removed
 
-#[macro_reexport(macro_one)] //~ ERROR cannot find attribute macro `macro_reexport` in this scope
+#[macro_reexport(macro_one)] //~ ERROR cannot find attribute `macro_reexport` in this scope
 extern crate two_macros;
 
 fn main() {}
diff --git a/src/test/ui/macros/macro-reexport-removed.stderr b/src/test/ui/macros/macro-reexport-removed.stderr
index 25778fb..4bec708 100644
--- a/src/test/ui/macros/macro-reexport-removed.stderr
+++ b/src/test/ui/macros/macro-reexport-removed.stderr
@@ -10,7 +10,7 @@
 LL | #![feature(macro_reexport)]
    |            ^^^^^^^^^^^^^^
 
-error: cannot find attribute macro `macro_reexport` in this scope
+error: cannot find attribute `macro_reexport` in this scope
   --> $DIR/macro-reexport-removed.rs:5:3
    |
 LL | #[macro_reexport(macro_one)]
diff --git a/src/test/ui/macros/macro-use-wrong-name.stderr b/src/test/ui/macros/macro-use-wrong-name.stderr
index 28f727d..8b4e90a 100644
--- a/src/test/ui/macros/macro-use-wrong-name.stderr
+++ b/src/test/ui/macros/macro-use-wrong-name.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `macro_two!` in this scope
+error: cannot find macro `macro_two` in this scope
   --> $DIR/macro-use-wrong-name.rs:7:5
    |
 LL |     macro_two!();
diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr
index 9239b2a..01c8ebe 100644
--- a/src/test/ui/macros/macro_undefined.stderr
+++ b/src/test/ui/macros/macro_undefined.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `k!` in this scope
+error: cannot find macro `k` in this scope
   --> $DIR/macro_undefined.rs:11:5
    |
 LL |     k!();
diff --git a/src/test/ui/main-wrong-location.rs b/src/test/ui/main-wrong-location.rs
index d7ed512..f75d088 100644
--- a/src/test/ui/main-wrong-location.rs
+++ b/src/test/ui/main-wrong-location.rs
@@ -1,4 +1,5 @@
 mod m {
+//~^ ERROR `main` function not found
     // An inferred main entry point (that doesn't use #[main])
     // must appear at the top of the crate
     fn main() { }
diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr
index b30931f..e301c2f 100644
--- a/src/test/ui/main-wrong-location.stderr
+++ b/src/test/ui/main-wrong-location.stderr
@@ -1,11 +1,21 @@
 error[E0601]: `main` function not found in crate `main_wrong_location`
+  --> $DIR/main-wrong-location.rs:1:1
    |
-   = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior.
-note: here is a function named 'main'
-  --> $DIR/main-wrong-location.rs:4:5
+LL | / mod m {
+LL | |
+LL | |     // An inferred main entry point (that doesn't use #[main])
+LL | |     // must appear at the top of the crate
+LL | |     fn main() { }
+LL | | }
+   | |_^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`)
+   |
+note: here is a function named `main`
+  --> $DIR/main-wrong-location.rs:5:5
    |
 LL |     fn main() { }
    |     ^^^^^^^^^^^^^
+   = note: you have one or more functions named `main` not defined at the crate level
+   = help: either move the `main` function definitions or attach the `#[main]` attribute to one of them
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr
index f4a52a6..4e79fbd 100644
--- a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr
+++ b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied
   --> $DIR/overlap-marker-trait.rs:27:5
    |
+LL | fn is_marker<T: Marker>() { }
+   | ------------------------- required by `is_marker`
+...
 LL |     is_marker::<NotDebugOrDisplay>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay`
-   |
-note: required by `is_marker`
-  --> $DIR/overlap-marker-trait.rs:15:1
-   |
-LL | fn is_marker<T: Marker>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr
index 663cd2c..c2298d6 100644
--- a/src/test/ui/match/match-pattern-field-mismatch.stderr
+++ b/src/test/ui/match/match-pattern-field-mismatch.stderr
@@ -1,6 +1,9 @@
 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
   --> $DIR/match-pattern-field-mismatch.rs:10:11
    |
+LL |         Rgb(usize, usize, usize),
+   |         ------------------------ tuple variant defined here
+...
 LL |           Color::Rgb(_, _) => { }
    |           ^^^^^^^^^^^^^^^^ expected 3 fields, found 2
 
diff --git a/src/test/ui/match/match-ref-mut-stability.rs b/src/test/ui/match/match-ref-mut-stability.rs
index 49e0dfa..5212036 100644
--- a/src/test/ui/match/match-ref-mut-stability.rs
+++ b/src/test/ui/match/match-ref-mut-stability.rs
@@ -3,8 +3,6 @@
 
 // run-pass
 
-#![feature(bind_by_move_pattern_guards)]
-
 // Test that z always point to the same temporary.
 fn referent_stability() {
     let p;
diff --git a/src/test/ui/match/match-vec-mismatch.stderr b/src/test/ui/match/match-vec-mismatch.stderr
index 2f1bbb7..a3523bb 100644
--- a/src/test/ui/match/match-vec-mismatch.stderr
+++ b/src/test/ui/match/match-vec-mismatch.stderr
@@ -10,7 +10,7 @@
 LL |         ['f', 'o', ..] => {}
    |         ^^^^^^^^^^^^^^ pattern cannot match with input type `std::string::String`
 
-error[E0527]: pattern requires 1 elements but array has 3
+error[E0527]: pattern requires 1 element but array has 3
   --> $DIR/match-vec-mismatch.rs:20:9
    |
 LL |         [0] => {},
diff --git a/src/test/ui/match/non-exhaustive-defined-here.rs b/src/test/ui/match/non-exhaustive-defined-here.rs
new file mode 100644
index 0000000..6f009ac
--- /dev/null
+++ b/src/test/ui/match/non-exhaustive-defined-here.rs
@@ -0,0 +1,72 @@
+// Test the "defined here" and "not covered" diagnostic hints.
+// We also make sure that references are peeled off from the scrutinee type
+// so that the diagnostics work better with default binding modes.
+
+#[derive(Clone)]
+enum E {
+//~^ `E` defined here
+//~| `E` defined here
+//~| `E` defined here
+//~| `E` defined here
+//~| `E` defined here
+//~| `E` defined here
+    A,
+    B,
+    //~^ not covered
+    //~| not covered
+    //~| not covered
+    //~| not covered
+    //~| not covered
+    //~| not covered
+    C
+    //~^ not covered
+    //~| not covered
+    //~| not covered
+    //~| not covered
+    //~| not covered
+    //~| not covered
+}
+
+fn by_val(e: E) {
+    let e1 = e.clone();
+    match e1 { //~ ERROR non-exhaustive patterns: `B` and `C` not covered
+        E::A => {}
+    }
+
+    let E::A = e; //~ ERROR refutable pattern in local binding: `B` and `C` not covered
+}
+
+fn by_ref_once(e: &E) {
+    match e { //~ ERROR non-exhaustive patterns: `&B` and `&C` not covered
+        E::A => {}
+    }
+
+    let E::A = e; //~ ERROR refutable pattern in local binding: `&B` and `&C` not covered
+}
+
+fn by_ref_thrice(e: & &mut &E) {
+    match e { //~ ERROR non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
+        E::A => {}
+    }
+
+    let E::A = e;
+    //~^ ERROR refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered
+}
+
+enum Opt {
+//~^ `Opt` defined here
+//~| `Opt` defined here
+    Some(u8),
+    None,
+    //~^ not covered
+}
+
+fn ref_pat(e: Opt) {
+    match e {//~ ERROR non-exhaustive patterns: `None` not covered
+        Opt::Some(ref _x) => {}
+    }
+
+    let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `None` not covered
+}
+
+fn main() {}
diff --git a/src/test/ui/match/non-exhaustive-defined-here.stderr b/src/test/ui/match/non-exhaustive-defined-here.stderr
new file mode 100644
index 0000000..25b8bbd
--- /dev/null
+++ b/src/test/ui/match/non-exhaustive-defined-here.stderr
@@ -0,0 +1,170 @@
+error[E0004]: non-exhaustive patterns: `B` and `C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:32:11
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       match e1 {
+   |             ^^ patterns `B` and `C` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0005]: refutable pattern in local binding: `B` and `C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:36:9
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       let E::A = e;
+   |           ^^^^ patterns `B` and `C` not covered
+
+error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:40:11
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       match e {
+   |             ^ patterns `&B` and `&C` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0005]: refutable pattern in local binding: `&B` and `&C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:44:9
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       let E::A = e;
+   |           ^^^^ patterns `&B` and `&C` not covered
+
+error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:48:11
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       match e {
+   |             ^ patterns `&&mut &B` and `&&mut &C` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0005]: refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:52:9
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       let E::A = e;
+   |           ^^^^ patterns `&&mut &B` and `&&mut &C` not covered
+
+error[E0004]: non-exhaustive patterns: `None` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:65:11
+   |
+LL | / enum Opt {
+LL | |
+LL | |
+LL | |     Some(u8),
+LL | |     None,
+   | |     ---- not covered
+LL | |
+LL | | }
+   | |_- `Opt` defined here
+...
+LL |       match e {
+   |             ^ pattern `None` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0005]: refutable pattern in local binding: `None` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:69:9
+   |
+LL | / enum Opt {
+LL | |
+LL | |
+LL | |     Some(u8),
+LL | |     None,
+   | |     ---- not covered
+LL | |
+LL | | }
+   | |_- `Opt` defined here
+...
+LL |       let Opt::Some(ref _x) = e;
+   |           ^^^^^^^^^^^^^^^^^ pattern `None` not covered
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index b8ae4c3..94c27b7 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -32,7 +32,7 @@
    | --------------- method `take` not found for this
 ...
 LL |      .take()
-   |       ^^^^
+   |       ^^^^ method not found in `Foo`
    |
    = note: the method `take` exists but the following trait bounds were not satisfied:
            `&mut Foo : std::iter::Iterator`
diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr
index 8662bb7..319eb86 100644
--- a/src/test/ui/mismatched_types/E0631.stderr
+++ b/src/test/ui/mismatched_types/E0631.stderr
@@ -1,60 +1,48 @@
 error[E0631]: type mismatch in closure arguments
   --> $DIR/E0631.rs:7:5
    |
+LL | fn foo<F: Fn(usize)>(_: F) {}
+   | -------------------------- required by `foo`
+...
 LL |     foo(|_: isize| {});
    |     ^^^ ---------- found signature of `fn(isize) -> _`
    |     |
    |     expected signature of `fn(usize) -> _`
-   |
-note: required by `foo`
-  --> $DIR/E0631.rs:3:1
-   |
-LL | fn foo<F: Fn(usize)>(_: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/E0631.rs:8:5
    |
+LL | fn bar<F: Fn<usize>>(_: F) {}
+   | -------------------------- required by `bar`
+...
 LL |     bar(|_: isize| {});
    |     ^^^ ---------- found signature of `fn(isize) -> _`
    |     |
    |     expected signature of `fn(usize) -> _`
-   |
-note: required by `bar`
-  --> $DIR/E0631.rs:4:1
-   |
-LL | fn bar<F: Fn<usize>>(_: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/E0631.rs:9:5
    |
+LL | fn foo<F: Fn(usize)>(_: F) {}
+   | -------------------------- required by `foo`
+...
 LL |     fn f(_: u64) {}
    |     ------------ found signature of `fn(u64) -> _`
 ...
 LL |     foo(f);
    |     ^^^ expected signature of `fn(usize) -> _`
-   |
-note: required by `foo`
-  --> $DIR/E0631.rs:3:1
-   |
-LL | fn foo<F: Fn(usize)>(_: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/E0631.rs:10:5
    |
+LL | fn bar<F: Fn<usize>>(_: F) {}
+   | -------------------------- required by `bar`
+LL | fn main() {
 LL |     fn f(_: u64) {}
    |     ------------ found signature of `fn(u64) -> _`
 ...
 LL |     bar(f);
    |     ^^^ expected signature of `fn(usize) -> _`
-   |
-note: required by `bar`
-  --> $DIR/E0631.rs:4:1
-   |
-LL | fn bar<F: Fn<usize>>(_: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index 25d5d25..b7b5b50 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -45,16 +45,13 @@
 error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
   --> $DIR/closure-arg-count.rs:13:5
    |
+LL | fn f<F: Fn<usize>>(_: F) {}
+   | ------------------------ required by `f`
+...
 LL |     f(|| panic!());
    |     ^ -- takes 0 arguments
    |     |
    |     expected closure that takes 1 argument
-   |
-note: required by `f`
-  --> $DIR/closure-arg-count.rs:3:1
-   |
-LL | fn f<F: Fn<usize>>(_: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider changing the closure to take and ignore the expected argument
    |
 LL |     f(|_| panic!());
@@ -63,16 +60,13 @@
 error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
   --> $DIR/closure-arg-count.rs:15:5
    |
+LL | fn f<F: Fn<usize>>(_: F) {}
+   | ------------------------ required by `f`
+...
 LL |     f(  move    || panic!());
    |     ^   ---------- takes 0 arguments
    |     |
    |     expected closure that takes 1 argument
-   |
-note: required by `f`
-  --> $DIR/closure-arg-count.rs:3:1
-   |
-LL | fn f<F: Fn<usize>>(_: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider changing the closure to take and ignore the expected argument
    |
 LL |     f(  move    |_| panic!());
@@ -148,14 +142,10 @@
 LL |     call(Foo);
    |     ^^^^ expected function that takes 0 arguments
 ...
+LL | fn call<F, R>(_: F) where F: FnOnce() -> R {}
+   | ------------------------------------------ required by `call`
 LL | struct Foo(u8);
    | --------------- takes 1 argument
-   |
-note: required by `call`
-  --> $DIR/closure-arg-count.rs:42:1
-   |
-LL | fn call<F, R>(_: F) where F: FnOnce() -> R {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 14 previous errors
 
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 d4ccf8d..2a65759 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -25,29 +25,23 @@
 error[E0631]: type mismatch in function arguments
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   | ------------------------------ required by `baz`
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
 LL |     baz(f);
    |     ^^^
    |     |
    |     expected signature of `for<'r> fn(*mut &'r u32) -> _`
    |     found signature of `fn(*mut &'a u32) -> _`
-   |
-note: required by `baz`
-  --> $DIR/closure-arg-type-mismatch.rs:8:1
-   |
-LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()`
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   | ------------------------------ required by `baz`
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
 LL |     baz(f);
    |     ^^^ expected bound lifetime parameter, found concrete lifetime
-   |
-note: required by `baz`
-  --> $DIR/closure-arg-type-mismatch.rs:8:1
-   |
-LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index 7161f69..0fe4909 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -1,30 +1,26 @@
 error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()`
   --> $DIR/closure-mismatch.rs:8:5
    |
+LL | fn baz<T: Foo>(_: T) {}
+   | -------------------- required by `baz`
+...
 LL |     baz(|_| ());
    |     ^^^ expected bound lifetime parameter, found concrete lifetime
    |
    = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]`
-note: required by `baz`
-  --> $DIR/closure-mismatch.rs:5:1
-   |
-LL | fn baz<T: Foo>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-mismatch.rs:8:5
    |
+LL | fn baz<T: Foo>(_: T) {}
+   | -------------------- required by `baz`
+...
 LL |     baz(|_| ());
    |     ^^^ ------ found signature of `fn(_) -> _`
    |     |
    |     expected signature of `for<'r> fn(&'r ()) -> _`
    |
    = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]`
-note: required by `baz`
-  --> $DIR/closure-mismatch.rs:5:1
-   |
-LL | fn baz<T: Foo>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
index c15d662..d4db7bd 100644
--- a/src/test/ui/mismatched_types/fn-variance-1.stderr
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -3,15 +3,12 @@
    |
 LL | fn takes_mut(x: &mut isize) { }
    | --------------------------- found signature of `for<'r> fn(&'r mut isize) -> _`
+LL | 
+LL | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
+   | --------------------------------------------- required by `apply`
 ...
 LL |     apply(&3, takes_mut);
    |     ^^^^^ expected signature of `fn(&{integer}) -> _`
-   |
-note: required by `apply`
-  --> $DIR/fn-variance-1.rs:5:1
-   |
-LL | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/fn-variance-1.rs:15:5
@@ -19,14 +16,11 @@
 LL | fn takes_imm(x: &isize) { }
    | ----------------------- found signature of `for<'r> fn(&'r isize) -> _`
 ...
+LL | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
+   | --------------------------------------------- required by `apply`
+...
 LL |     apply(&mut 3, takes_imm);
    |     ^^^^^ expected signature of `fn(&mut {integer}) -> _`
-   |
-note: required by `apply`
-  --> $DIR/fn-variance-1.rs:5:1
-   |
-LL | fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index 3f87ef7..89c7b09 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-36053-2.rs:7:55
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
-   |                                                       ^^^^^
+   |                                                       ^^^^^ method not found in `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`
    |
    = note: the method `count` exists but the following trait bounds were not satisfied:
            `&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator`
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
index 9721dc8..865092e 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -2,7 +2,7 @@
   --> $DIR/method-help-unsatisfied-bound.rs:5:7
    |
 LL |     a.unwrap();
-   |       ^^^^^^
+   |       ^^^^^^ method not found in `std::result::Result<(), Foo>`
    |
    = note: the method `unwrap` exists but the following trait bounds were not satisfied:
            `Foo : std::fmt::Debug`
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 47aa3c2..53c9fcd 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -1,17 +1,14 @@
 error[E0631]: type mismatch in closure arguments
   --> $DIR/unboxed-closures-vtable-mismatch.rs:15:13
    |
+LL | fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
+   | -------------------------------------------------------------------- required by `call_it`
+...
 LL |     let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
    |                       ----------------------------- found signature of `fn(usize, isize) -> _`
 LL |
 LL |     let z = call_it(3, f);
    |             ^^^^^^^ expected signature of `fn(isize, isize) -> _`
-   |
-note: required by `call_it`
-  --> $DIR/unboxed-closures-vtable-mismatch.rs:7:1
-   |
-LL | fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/missing/missing-macro-use.rs b/src/test/ui/missing/missing-macro-use.rs
index dff4c94..d494c44 100644
--- a/src/test/ui/missing/missing-macro-use.rs
+++ b/src/test/ui/missing/missing-macro-use.rs
@@ -4,5 +4,5 @@
 
 pub fn main() {
     macro_two!();
-    //~^ ERROR cannot find macro `macro_two!` in this scope
+    //~^ ERROR cannot find macro `macro_two` in this scope
 }
diff --git a/src/test/ui/missing/missing-macro-use.stderr b/src/test/ui/missing/missing-macro-use.stderr
index 01a7beb..711e249 100644
--- a/src/test/ui/missing/missing-macro-use.stderr
+++ b/src/test/ui/missing/missing-macro-use.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `macro_two!` in this scope
+error: cannot find macro `macro_two` in this scope
   --> $DIR/missing-macro-use.rs:6:5
    |
 LL |     macro_two!();
diff --git a/src/test/ui/missing/missing-main.stderr b/src/test/ui/missing/missing-main.stderr
index 34b03ad..6a35f51 100644
--- a/src/test/ui/missing/missing-main.stderr
+++ b/src/test/ui/missing/missing-main.stderr
@@ -1,6 +1,8 @@
 error[E0601]: `main` function not found in crate `missing_main`
+  --> $DIR/missing-main.rs:2:1
    |
-   = note: consider adding a `main` function to `$DIR/missing-main.rs`
+LL | fn mian() { }
+   | ^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/missing-main.rs`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/missing/missing-semicolon-warning.stderr b/src/test/ui/missing/missing-semicolon-warning.stderr
index b3f3ebc..b4001ab 100644
--- a/src/test/ui/missing/missing-semicolon-warning.stderr
+++ b/src/test/ui/missing/missing-semicolon-warning.stderr
@@ -7,7 +7,7 @@
 LL | fn main() { m!(0, 0; 0, 0); }
    |             --------------- in this macro invocation
    |
-   = note: This was erroneously allowed and will become a hard error in a future release
+   = note: this was erroneously allowed and will become a hard error in a future release
 
 warning: expected `;`, found `println`
   --> $DIR/missing-semicolon-warning.rs:7:12
@@ -18,5 +18,5 @@
 LL | fn main() { m!(0, 0; 0, 0); }
    |             --------------- in this macro invocation
    |
-   = note: This was erroneously allowed and will become a hard error in a future release
+   = note: this was erroneously allowed and will become a hard error in a future release
 
diff --git a/src/test/ui/moves/move-into-dead-array-1.rs b/src/test/ui/moves/move-into-dead-array-1.rs
index 16a18da..2d0ff58 100644
--- a/src/test/ui/moves/move-into-dead-array-1.rs
+++ b/src/test/ui/moves/move-into-dead-array-1.rs
@@ -11,5 +11,5 @@
 
 fn foo(i: usize) {
     let mut a: [D; 4];
-    a[i] = d();        //~ ERROR use of possibly uninitialized variable: `a`
+    a[i] = d();        //~ ERROR use of possibly-uninitialized variable: `a`
 }
diff --git a/src/test/ui/moves/move-into-dead-array-1.stderr b/src/test/ui/moves/move-into-dead-array-1.stderr
index 33da0e54..5f20ccf 100644
--- a/src/test/ui/moves/move-into-dead-array-1.stderr
+++ b/src/test/ui/moves/move-into-dead-array-1.stderr
@@ -1,8 +1,8 @@
-error[E0381]: use of possibly uninitialized variable: `a`
+error[E0381]: use of possibly-uninitialized variable: `a`
   --> $DIR/move-into-dead-array-1.rs:14:5
    |
 LL |     a[i] = d();
-   |     ^^^^ use of possibly uninitialized `a`
+   |     ^^^^ use of possibly-uninitialized `a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/mut/mutable-enum-indirect.stderr b/src/test/ui/mut/mutable-enum-indirect.stderr
index 1268e48..4efb10b 100644
--- a/src/test/ui/mut/mutable-enum-indirect.stderr
+++ b/src/test/ui/mut/mutable-enum-indirect.stderr
@@ -1,17 +1,15 @@
 error[E0277]: `NoSync` cannot be shared between threads safely
   --> $DIR/mutable-enum-indirect.rs:17:5
    |
+LL | fn bar<T: Sync>(_: T) {}
+   | --------------------- required by `bar`
+...
 LL |     bar(&x);
    |     ^^^ `NoSync` cannot be shared between threads safely
    |
    = help: within `&Foo`, the trait `std::marker::Sync` is not implemented for `NoSync`
    = note: required because it appears within the type `Foo`
    = note: required because it appears within the type `&Foo`
-note: required by `bar`
-  --> $DIR/mutable-enum-indirect.rs:13:1
-   |
-LL | fn bar<T: Sync>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/mutexguard-sync.stderr b/src/test/ui/mutexguard-sync.stderr
index d1f7d13..4a93c9f 100644
--- a/src/test/ui/mutexguard-sync.stderr
+++ b/src/test/ui/mutexguard-sync.stderr
@@ -1,16 +1,14 @@
 error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
   --> $DIR/mutexguard-sync.rs:11:5
    |
+LL | fn test_sync<T: Sync>(_t: T) {}
+   | ---------------------------- required by `test_sync`
+...
 LL |     test_sync(guard);
    |     ^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
    = note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::MutexGuard<'_, std::cell::Cell<i32>>`
-note: required by `test_sync`
-  --> $DIR/mutexguard-sync.rs:5:1
-   |
-LL | fn test_sync<T: Sync>(_t: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index ef2d0d8..39aaddb 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -69,530 +69,398 @@
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:33:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m1::S{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::S: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:35:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m2::S{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::S`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:36:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m2::S);
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:39:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm1::S{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::S: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:41:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm2::S{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:42:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm2::S);
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:55:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m3::TS{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:56:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m3::TS);
    |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::TS: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:57:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m4::TS{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::TS`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:58:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m4::TS);
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:61:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm3::TS{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:62:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm3::TS);
    |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::TS: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:63:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm4::TS{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:64:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm4::TS);
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:77:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m5::US{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::US: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:78:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m5::US);
    |     ^^^^^ the trait `Impossible` is not implemented for `c::US`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::US: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:79:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m6::US{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::US`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:80:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m6::US);
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:83:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm5::US{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:84:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm5::US);
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:85:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm6::US{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:86:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm6::US);
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:99:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m7::V{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:101:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m8::V{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::E`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:102:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m8::V);
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:105:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm7::V{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:107:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm8::V{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:108:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm8::V);
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:121:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m9::TV{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:122:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(m9::TV);
    |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:123:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(mA::TV{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::E`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:124:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(mA::TV);
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:127:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm9::TV{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:128:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xm9::TV);
    |     ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:129:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xmA::TV{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:130:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xmA::TV);
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:143:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(mB::UV{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:144:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(mB::UV);
    |     ^^^^^ the trait `Impossible` is not implemented for `c::E`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:145:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(mC::UV{});
    |     ^^^^^ the trait `Impossible` is not implemented for `c::E`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:146:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(mC::UV);
    |     ^^^^^ the trait `Impossible` is not implemented for `c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:149:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xmB::UV{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:150:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xmB::UV);
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:151:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xmC::UV{});
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:152:5
    |
+LL | fn check<T: Impossible>(_: T) {}
+   | ----------------------------- required by `check`
+...
 LL |     check(xmC::UV);
    |     ^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
-   |
-note: required by `check`
-  --> $DIR/namespace-mix.rs:21:1
-   |
-LL | fn check<T: Impossible>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 48 previous errors
 
diff --git a/src/test/ui/never-assign-dead-code.stderr b/src/test/ui/never-assign-dead-code.stderr
index 779780a..b1b5bf0 100644
--- a/src/test/ui/never-assign-dead-code.stderr
+++ b/src/test/ui/never-assign-dead-code.stderr
@@ -11,11 +11,11 @@
    |         ^^^^^^
    = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]`
 
-warning: unreachable expression
+warning: unreachable call
   --> $DIR/never-assign-dead-code.rs:10:5
    |
 LL |     drop(x);
-   |     ^^^^^^^
+   |     ^^^^
 
 warning: unused variable: `x`
   --> $DIR/never-assign-dead-code.rs:9:9
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
index 906ea32..1983e13 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
@@ -26,13 +26,13 @@
 fn cannot_partially_init_adt_with_drop() {
     let d: D;
     d.x = 10;
-    //~^ ERROR assign of possibly uninitialized variable: `d` [E0381]
+    //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381]
 }
 
 fn cannot_partially_init_mutable_adt_with_drop() {
     let mut d: D;
     d.x = 10;
-    //~^ ERROR assign of possibly uninitialized variable: `d` [E0381]
+    //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381]
 }
 
 fn cannot_partially_reinit_adt_with_drop() {
@@ -45,13 +45,13 @@
 fn cannot_partially_init_inner_adt_via_outer_with_drop() {
     let d: D;
     d.s.y = 20;
-    //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381]
 }
 
 fn cannot_partially_init_inner_adt_via_mutable_outer_with_drop() {
     let mut d: D;
     d.s.y = 20;
-    //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381]
 }
 
 fn cannot_partially_reinit_inner_adt_via_outer_with_drop() {
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
index 153d9bd..1b66e03 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
@@ -1,14 +1,14 @@
-error[E0381]: assign of possibly uninitialized variable: `d`
+error[E0381]: assign of possibly-uninitialized variable: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:28:5
    |
 LL |     d.x = 10;
-   |     ^^^^^^^^ use of possibly uninitialized `d`
+   |     ^^^^^^^^ use of possibly-uninitialized `d`
 
-error[E0381]: assign of possibly uninitialized variable: `d`
+error[E0381]: assign of possibly-uninitialized variable: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:34:5
    |
 LL |     d.x = 10;
-   |     ^^^^^^^^ use of possibly uninitialized `d`
+   |     ^^^^^^^^ use of possibly-uninitialized `d`
 
 error[E0382]: assign of moved value: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:41:5
@@ -20,17 +20,17 @@
 LL |     d.x = 10;
    |     ^^^^^^^^ value assigned here after move
 
-error[E0381]: assign to part of possibly uninitialized variable: `d`
+error[E0381]: assign to part of possibly-uninitialized variable: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:47:5
    |
 LL |     d.s.y = 20;
-   |     ^^^^^^^^^^ use of possibly uninitialized `d.s`
+   |     ^^^^^^^^^^ use of possibly-uninitialized `d.s`
 
-error[E0381]: assign to part of possibly uninitialized variable: `d`
+error[E0381]: assign to part of possibly-uninitialized variable: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:53:5
    |
 LL |     d.s.y = 20;
-   |     ^^^^^^^^^^ use of possibly uninitialized `d.s`
+   |     ^^^^^^^^^^ use of possibly-uninitialized `d.s`
 
 error[E0382]: assign to part of moved value: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:60:5
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs
index 633cbdb..7da47c8 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-use.rs
+++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs
@@ -97,14 +97,14 @@
 fn test_0000_local_fully_init_and_use_struct() {
     let s: S<B>;
     s.x = 10; s.y = Box::new(20);
-    //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381]
     use_fully!(struct s);
 }
 
 fn test_0001_local_fully_init_and_use_tuple() {
     let t: T;
     t.0 = 10; t.1 = Box::new(20);
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
     use_fully!(tuple t);
 }
 
@@ -125,14 +125,14 @@
 fn test_0100_local_partial_init_and_use_struct() {
     let s: S<B>;
     s.x = 10;
-    //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381]
     use_part!(struct s);
 }
 
 fn test_0101_local_partial_init_and_use_tuple() {
     let t: T;
     t.0 = 10;
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
     use_part!(tuple t);
 }
 
@@ -153,14 +153,14 @@
 fn test_0200_local_void_init_and_use_struct() {
     let s: S<Void>;
     s.x = 10;
-    //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381]
     use_part!(struct s);
 }
 
 fn test_0201_local_void_init_and_use_tuple() {
     let t: Tvoid;
     t.0 = 10;
-    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
     use_part!(tuple t);
 }
 
@@ -176,14 +176,14 @@
 fn test_1000_field_fully_init_and_use_struct() {
     let q: Q<S<B>>;
     q.r.f.x = 10; q.r.f.y = Box::new(20);
-    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
     use_fully!(struct q.r.f);
 }
 
 fn test_1001_field_fully_init_and_use_tuple() {
     let q: Q<T>;
     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
-    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
     use_fully!(tuple q.r.f);
 }
 
@@ -204,14 +204,14 @@
 fn test_1100_field_partial_init_and_use_struct() {
     let q: Q<S<B>>;
     q.r.f.x = 10;
-    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
     use_part!(struct q.r.f);
 }
 
 fn test_1101_field_partial_init_and_use_tuple() {
     let q: Q<T>;
     q.r.f.0 = 10;
-    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
     use_part!(tuple q.r.f);
 }
 
@@ -232,14 +232,14 @@
 fn test_1200_field_void_init_and_use_struct() {
     let mut q: Q<S<Void>>;
     q.r.f.x = 10;
-    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
     use_part!(struct q.r.f);
 }
 
 fn test_1201_field_void_init_and_use_tuple() {
     let mut q: Q<Tvoid>;
     q.r.f.0 = 10;
-    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
     use_part!(tuple q.r.f);
 }
 
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
index 1cdf728..3214789 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
@@ -1,14 +1,14 @@
-error[E0381]: assign to part of possibly uninitialized variable: `s`
+error[E0381]: assign to part of possibly-uninitialized variable: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:99:5
    |
 LL |     s.x = 10; s.y = Box::new(20);
-   |     ^^^^^^^^ use of possibly uninitialized `s`
+   |     ^^^^^^^^ use of possibly-uninitialized `s`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/issue-21232-partial-init-and-use.rs:106:5
    |
 LL |     t.0 = 10; t.1 = Box::new(20);
-   |     ^^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^^ use of possibly-uninitialized `t`
 
 error[E0382]: assign to part of moved value: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:113:5
@@ -30,17 +30,17 @@
 LL |     t.0 = 10; t.1 = Box::new(20);
    |     ^^^^^^^^ value partially assigned here after move
 
-error[E0381]: assign to part of possibly uninitialized variable: `s`
+error[E0381]: assign to part of possibly-uninitialized variable: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:127:5
    |
 LL |     s.x = 10;
-   |     ^^^^^^^^ use of possibly uninitialized `s`
+   |     ^^^^^^^^ use of possibly-uninitialized `s`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/issue-21232-partial-init-and-use.rs:134:5
    |
 LL |     t.0 = 10;
-   |     ^^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^^ use of possibly-uninitialized `t`
 
 error[E0382]: assign to part of moved value: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:141:5
@@ -62,29 +62,29 @@
 LL |     t.0 = 10;
    |     ^^^^^^^^ value partially assigned here after move
 
-error[E0381]: assign to part of possibly uninitialized variable: `s`
+error[E0381]: assign to part of possibly-uninitialized variable: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:155:5
    |
 LL |     s.x = 10;
-   |     ^^^^^^^^ use of possibly uninitialized `s`
+   |     ^^^^^^^^ use of possibly-uninitialized `s`
 
-error[E0381]: assign to part of possibly uninitialized variable: `t`
+error[E0381]: assign to part of possibly-uninitialized variable: `t`
   --> $DIR/issue-21232-partial-init-and-use.rs:162:5
    |
 LL |     t.0 = 10;
-   |     ^^^^^^^^ use of possibly uninitialized `t`
+   |     ^^^^^^^^ use of possibly-uninitialized `t`
 
-error[E0381]: assign to part of possibly uninitialized variable: `q`
+error[E0381]: assign to part of possibly-uninitialized variable: `q`
   --> $DIR/issue-21232-partial-init-and-use.rs:178:5
    |
 LL |     q.r.f.x = 10; q.r.f.y = Box::new(20);
-   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
 
-error[E0381]: assign to part of possibly uninitialized variable: `q`
+error[E0381]: assign to part of possibly-uninitialized variable: `q`
   --> $DIR/issue-21232-partial-init-and-use.rs:185:5
    |
 LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
-   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
 
 error[E0382]: assign to part of moved value: `q.r`
   --> $DIR/issue-21232-partial-init-and-use.rs:192:5
@@ -106,17 +106,17 @@
    |
    = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box<u32>)>`, which does not implement the `Copy` trait
 
-error[E0381]: assign to part of possibly uninitialized variable: `q`
+error[E0381]: assign to part of possibly-uninitialized variable: `q`
   --> $DIR/issue-21232-partial-init-and-use.rs:206:5
    |
 LL |     q.r.f.x = 10;
-   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
 
-error[E0381]: assign to part of possibly uninitialized variable: `q`
+error[E0381]: assign to part of possibly-uninitialized variable: `q`
   --> $DIR/issue-21232-partial-init-and-use.rs:213:5
    |
 LL |     q.r.f.0 = 10;
-   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
 
 error[E0382]: assign to part of moved value: `q.r`
   --> $DIR/issue-21232-partial-init-and-use.rs:220:5
@@ -138,17 +138,17 @@
    |
    = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box<u32>)>`, which does not implement the `Copy` trait
 
-error[E0381]: assign to part of possibly uninitialized variable: `q`
+error[E0381]: assign to part of possibly-uninitialized variable: `q`
   --> $DIR/issue-21232-partial-init-and-use.rs:234:5
    |
 LL |     q.r.f.x = 10;
-   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
 
-error[E0381]: assign to part of possibly uninitialized variable: `q`
+error[E0381]: assign to part of possibly-uninitialized variable: `q`
   --> $DIR/issue-21232-partial-init-and-use.rs:241:5
    |
 LL |     q.r.f.0 = 10;
-   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
 
 error[E0382]: assign to part of moved value: `c`
   --> $DIR/issue-21232-partial-init-and-use.rs:259:13
diff --git a/src/test/ui/nll/issue-55288.rs b/src/test/ui/nll/issue-55288.rs
index c7b6ac5..aab2dc2 100644
--- a/src/test/ui/nll/issue-55288.rs
+++ b/src/test/ui/nll/issue-55288.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 struct Slice(&'static [&'static [u8]]);
 
diff --git a/src/test/ui/nll/issue-57960.rs b/src/test/ui/nll/issue-57960.rs
index 1399694..32e4518 100644
--- a/src/test/ui/nll/issue-57960.rs
+++ b/src/test/ui/nll/issue-57960.rs
@@ -30,7 +30,6 @@
         OneDigit::FIRST..=OneDigit::LAST => 1,
         TwoDigits::FIRST..=TwoDigits::LAST => 2,
         ThreeDigits::FIRST..=ThreeDigits::LAST => 3,
-        _ => unreachable!(),
     }
 }
 
diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs
index 94e4a76..2e6d675 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.rs
+++ b/src/test/ui/nll/match-cfg-fake-edges.rs
@@ -1,8 +1,6 @@
 // Test that we have enough false edges to avoid exposing the exact matching
 // algorithm in borrow checking.
 
-#![feature(bind_by_move_pattern_guards)]
-
 fn guard_always_precedes_arm(y: i32) {
     let mut x;
     // x should always be initialized, as the only way to reach the arm is
@@ -20,7 +18,7 @@
     match y {
         _ if { x = 2; true } => 1,
         _ if {
-            x; //~ ERROR use of possibly uninitialized variable: `x`
+            x; //~ ERROR use of possibly-uninitialized variable: `x`
             false
         } => 2,
         _ => 3,
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
index b1e0fa7..06fe564 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.stderr
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -1,11 +1,11 @@
-error[E0381]: use of possibly uninitialized variable: `x`
-  --> $DIR/match-cfg-fake-edges.rs:23:13
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/match-cfg-fake-edges.rs:21:13
    |
 LL |             x;
-   |             ^ use of possibly uninitialized `x`
+   |             ^ use of possibly-uninitialized `x`
 
 error[E0382]: use of moved value: `x`
-  --> $DIR/match-cfg-fake-edges.rs:37:13
+  --> $DIR/match-cfg-fake-edges.rs:35:13
    |
 LL |     let x = String::new();
    |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs
index 601c46f..81ae19e 100644
--- a/src/test/ui/nll/match-guards-partially-borrow.rs
+++ b/src/test/ui/nll/match-guards-partially-borrow.rs
@@ -5,8 +5,6 @@
 // Test that we don't allow mutating the value being matched on in a way that
 // changes which patterns it matches, until we have chosen an arm.
 
-#![feature(bind_by_move_pattern_guards)]
-
 fn ok_mutation_in_guard(mut q: i32) {
     match q {
         // OK, mutation doesn't change which patterns g matches
diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr
index b2951fd..48e3a7c 100644
--- a/src/test/ui/nll/match-guards-partially-borrow.stderr
+++ b/src/test/ui/nll/match-guards-partially-borrow.stderr
@@ -1,5 +1,5 @@
 error[E0510]: cannot assign `q` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:57:13
+  --> $DIR/match-guards-partially-borrow.rs:55:13
    |
 LL |     match q {
    |           - value is immutable in match guard
@@ -8,7 +8,7 @@
    |             ^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `r` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:69:13
+  --> $DIR/match-guards-partially-borrow.rs:67:13
    |
 LL |     match r {
    |           - value is immutable in match guard
@@ -17,7 +17,7 @@
    |             ^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `t` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:93:13
+  --> $DIR/match-guards-partially-borrow.rs:91:13
    |
 LL |     match t {
    |           - value is immutable in match guard
@@ -26,7 +26,7 @@
    |             ^^^^^^^^ cannot assign
 
 error[E0510]: cannot mutably borrow `x.0` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:107:22
+  --> $DIR/match-guards-partially-borrow.rs:105:22
    |
 LL |     match x {
    |           - value is immutable in match guard
@@ -35,7 +35,7 @@
    |                      ^^^^^^^^^ cannot mutably borrow
 
 error[E0506]: cannot assign to `t` because it is borrowed
-  --> $DIR/match-guards-partially-borrow.rs:119:13
+  --> $DIR/match-guards-partially-borrow.rs:117:13
    |
 LL |         s if {
    |         - borrow of `t` occurs here
@@ -46,7 +46,7 @@
    |         - borrow later used here
 
 error[E0510]: cannot assign `y` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:130:13
+  --> $DIR/match-guards-partially-borrow.rs:128:13
    |
 LL |     match *y {
    |           -- value is immutable in match guard
@@ -55,7 +55,7 @@
    |             ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `z` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:141:13
+  --> $DIR/match-guards-partially-borrow.rs:139:13
    |
 LL |     match z {
    |           - value is immutable in match guard
@@ -64,7 +64,7 @@
    |             ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `a` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:153:13
+  --> $DIR/match-guards-partially-borrow.rs:151:13
    |
 LL |     match a {
    |           - value is immutable in match guard
@@ -73,7 +73,7 @@
    |             ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `b` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:164:13
+  --> $DIR/match-guards-partially-borrow.rs:162:13
    |
 LL |     match b {
    |           - value is immutable in match guard
diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr
index 9f804df..284a910 100644
--- a/src/test/ui/nll/match-on-borrowed.stderr
+++ b/src/test/ui/nll/match-on-borrowed.stderr
@@ -34,11 +34,11 @@
 LL |     x;
    |     - borrow later used here
 
-error[E0381]: use of possibly uninitialized variable: `n`
+error[E0381]: use of possibly-uninitialized variable: `n`
   --> $DIR/match-on-borrowed.rs:92:11
    |
 LL |     match n {}
-   |           ^ use of possibly uninitialized `n`
+   |           ^ use of possibly-uninitialized `n`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/nll/normalization-bounds.rs b/src/test/ui/nll/normalization-bounds.rs
index 5d2825e..bb6d981 100644
--- a/src/test/ui/nll/normalization-bounds.rs
+++ b/src/test/ui/nll/normalization-bounds.rs
@@ -1,6 +1,6 @@
 // Check that lifetime bounds get checked the right way around with NLL enabled.
 
-//run-pass
+// check-pass
 
 trait Visitor<'d> {
     type Value;
diff --git a/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs
index 6d5bdfa..3b06b0d 100644
--- a/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs
+++ b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs
@@ -1,11 +1,11 @@
 // Check that mutable promoted length zero arrays don't check for conflicting
 // access
 
-// run-pass
+// check-pass
 
 pub fn main() {
     let mut x: Vec<&[i32; 0]> = Vec::new();
-    for i in 0..10 {
+    for _ in 0..10 {
         x.push(&[]);
     }
 }
diff --git a/src/test/ui/nll/self-assign-ref-mut.rs b/src/test/ui/nll/self-assign-ref-mut.rs
new file mode 100644
index 0000000..1ca4cf3
--- /dev/null
+++ b/src/test/ui/nll/self-assign-ref-mut.rs
@@ -0,0 +1,20 @@
+// Check that `*y` isn't borrowed after `y = y`.
+
+// check-pass
+
+fn main() {
+    let mut x = 1;
+    {
+        let mut y = &mut x;
+        y = y;
+        y;
+    }
+    x;
+    {
+        let mut y = &mut x;
+        y = y;
+        y = y;
+        y;
+    }
+    x;
+}
diff --git a/src/test/ui/nll/user-annotations/issue-55219.rs b/src/test/ui/nll/user-annotations/issue-55219.rs
index 4d18e96..1474136 100644
--- a/src/test/ui/nll/user-annotations/issue-55219.rs
+++ b/src/test/ui/nll/user-annotations/issue-55219.rs
@@ -3,7 +3,7 @@
 // The `Self::HASH_LEN` here expands to a "self-type" where `T` is not
 // known. This unbound inference variable was causing an ICE.
 //
-// run-pass
+// check-pass
 
 pub struct Foo<T>(T);
 
diff --git a/src/test/ui/nll/user-annotations/normalize-self-ty.rs b/src/test/ui/nll/user-annotations/normalize-self-ty.rs
index a06229a..df905c8 100644
--- a/src/test/ui/nll/user-annotations/normalize-self-ty.rs
+++ b/src/test/ui/nll/user-annotations/normalize-self-ty.rs
@@ -2,7 +2,7 @@
 // the inherent impl requires normalization to be equal to the
 // user-provided type.
 //
-// run-pass
+// check-pass
 
 trait Mirror {
     type Me;
@@ -15,7 +15,7 @@
 struct Foo<A, B>(A, B);
 
 impl<A> Foo<A, <A as Mirror>::Me> {
-    fn m(b: A) { }
+    fn m(_: A) { }
 }
 
 fn main() {
diff --git a/src/test/ui/no_send-enum.stderr b/src/test/ui/no_send-enum.stderr
index 71e3aee..d1f3398 100644
--- a/src/test/ui/no_send-enum.stderr
+++ b/src/test/ui/no_send-enum.stderr
@@ -1,16 +1,14 @@
 error[E0277]: `NoSend` cannot be sent between threads safely
   --> $DIR/no_send-enum.rs:16:5
    |
+LL | fn bar<T: Send>(_: T) {}
+   | --------------------- required by `bar`
+...
 LL |     bar(x);
    |     ^^^ `NoSend` cannot be sent between threads safely
    |
    = help: within `Foo`, the trait `std::marker::Send` is not implemented for `NoSend`
    = note: required because it appears within the type `Foo`
-note: required by `bar`
-  --> $DIR/no_send-enum.rs:12:1
-   |
-LL | fn bar<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/no_send-rc.stderr b/src/test/ui/no_send-rc.stderr
index 2028cf7..eaf3103 100644
--- a/src/test/ui/no_send-rc.stderr
+++ b/src/test/ui/no_send-rc.stderr
@@ -1,15 +1,13 @@
 error[E0277]: `std::rc::Rc<{integer}>` cannot be sent between threads safely
   --> $DIR/no_send-rc.rs:7:5
    |
+LL | fn bar<T: Send>(_: T) {}
+   | --------------------- required by `bar`
+...
 LL |     bar(x);
    |     ^^^ `std::rc::Rc<{integer}>` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<{integer}>`
-note: required by `bar`
-  --> $DIR/no_send-rc.rs:3:1
-   |
-LL | fn bar<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/no_send-struct.stderr b/src/test/ui/no_send-struct.stderr
index ca4ae05..1808cef 100644
--- a/src/test/ui/no_send-struct.stderr
+++ b/src/test/ui/no_send-struct.stderr
@@ -1,15 +1,13 @@
 error[E0277]: `Foo` cannot be sent between threads safely
   --> $DIR/no_send-struct.rs:15:5
    |
+LL | fn bar<T: Send>(_: T) {}
+   | --------------------- required by `bar`
+...
 LL |     bar(x);
    |     ^^^ `Foo` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `Foo`
-note: required by `bar`
-  --> $DIR/no_send-struct.rs:11:1
-   |
-LL | fn bar<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/no_share-enum.stderr b/src/test/ui/no_share-enum.stderr
index 64d791d..5a9b7ca 100644
--- a/src/test/ui/no_share-enum.stderr
+++ b/src/test/ui/no_share-enum.stderr
@@ -1,16 +1,14 @@
 error[E0277]: `NoSync` cannot be shared between threads safely
   --> $DIR/no_share-enum.rs:14:5
    |
+LL | fn bar<T: Sync>(_: T) {}
+   | --------------------- required by `bar`
+...
 LL |     bar(x);
    |     ^^^ `NoSync` cannot be shared between threads safely
    |
    = help: within `Foo`, the trait `std::marker::Sync` is not implemented for `NoSync`
    = note: required because it appears within the type `Foo`
-note: required by `bar`
-  --> $DIR/no_share-enum.rs:10:1
-   |
-LL | fn bar<T: Sync>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/no_share-struct.stderr b/src/test/ui/no_share-struct.stderr
index fc4bcfb..c12ee7c 100644
--- a/src/test/ui/no_share-struct.stderr
+++ b/src/test/ui/no_share-struct.stderr
@@ -1,15 +1,13 @@
 error[E0277]: `Foo` cannot be shared between threads safely
   --> $DIR/no_share-struct.rs:12:5
    |
+LL | fn bar<T: Sync>(_: T) {}
+   | --------------------- required by `bar`
+...
 LL |     bar(x);
    |     ^^^ `Foo` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `Foo`
-note: required by `bar`
-  --> $DIR/no_share-struct.rs:8:1
-   |
-LL | fn bar<T: Sync>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr
index 4041e19..b05c29c 100644
--- a/src/test/ui/non-copyable-void.stderr
+++ b/src/test/ui/non-copyable-void.stderr
@@ -2,7 +2,7 @@
   --> $DIR/non-copyable-void.rs:11:23
    |
 LL |         let _z = (*y).clone();
-   |                       ^^^^^
+   |                       ^^^^^ method not found in `libc::c_void`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr
index eb47a33..c1c5021 100644
--- a/src/test/ui/noncopyable-class.stderr
+++ b/src/test/ui/noncopyable-class.stderr
@@ -5,7 +5,7 @@
    | ---------- method `clone` not found for this
 ...
 LL |     let _y = x.clone();
-   |                ^^^^^
+   |                ^^^^^ method not found in `Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
diff --git a/src/test/ui/not-panic/not-panic-safe-2.stderr b/src/test/ui/not-panic/not-panic-safe-2.stderr
index 4db127a..5bacf0b 100644
--- a/src/test/ui/not-panic/not-panic-safe-2.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-2.stderr
@@ -1,21 +1,22 @@
 error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-2.rs:10:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<Rc<RefCell<i32>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
    = note: required because it appears within the type `std::cell::RefCell<i32>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::rc::Rc<std::cell::RefCell<i32>>`
-note: required by `assert`
-  --> $DIR/not-panic-safe-2.rs:7:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-2.rs:10:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<Rc<RefCell<i32>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
@@ -23,11 +24,6 @@
    = note: required because it appears within the type `std::cell::Cell<isize>`
    = note: required because it appears within the type `std::cell::RefCell<i32>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::rc::Rc<std::cell::RefCell<i32>>`
-note: required by `assert`
-  --> $DIR/not-panic-safe-2.rs:7:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/not-panic/not-panic-safe-3.stderr b/src/test/ui/not-panic/not-panic-safe-3.stderr
index 1f87f20..6d2a450 100644
--- a/src/test/ui/not-panic/not-panic-safe-3.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-3.stderr
@@ -1,21 +1,22 @@
 error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-3.rs:10:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<Arc<RefCell<i32>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
    = note: required because it appears within the type `std::cell::RefCell<i32>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::sync::Arc<std::cell::RefCell<i32>>`
-note: required by `assert`
-  --> $DIR/not-panic-safe-3.rs:7:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-3.rs:10:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<Arc<RefCell<i32>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
@@ -23,11 +24,6 @@
    = note: required because it appears within the type `std::cell::Cell<isize>`
    = note: required because it appears within the type `std::cell::RefCell<i32>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::sync::Arc<std::cell::RefCell<i32>>`
-note: required by `assert`
-  --> $DIR/not-panic-safe-3.rs:7:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/not-panic/not-panic-safe-4.stderr b/src/test/ui/not-panic/not-panic-safe-4.stderr
index 24f6490..e28f169 100644
--- a/src/test/ui/not-panic/not-panic-safe-4.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-4.stderr
@@ -1,21 +1,22 @@
 error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-4.rs:9:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<&RefCell<i32>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
    = note: required because it appears within the type `std::cell::RefCell<i32>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::RefCell<i32>`
-note: required by `assert`
-  --> $DIR/not-panic-safe-4.rs:6:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-4.rs:9:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<&RefCell<i32>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
@@ -23,11 +24,6 @@
    = note: required because it appears within the type `std::cell::Cell<isize>`
    = note: required because it appears within the type `std::cell::RefCell<i32>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::RefCell<i32>`
-note: required by `assert`
-  --> $DIR/not-panic-safe-4.rs:6:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/not-panic/not-panic-safe-5.stderr b/src/test/ui/not-panic/not-panic-safe-5.stderr
index a603acb..f8c4fe6 100644
--- a/src/test/ui/not-panic/not-panic-safe-5.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-5.stderr
@@ -1,16 +1,14 @@
 error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-5.rs:9:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<*const UnsafeCell<i32>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*const std::cell::UnsafeCell<i32>`
-note: required by `assert`
-  --> $DIR/not-panic-safe-5.rs:6:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/not-panic/not-panic-safe-6.stderr b/src/test/ui/not-panic/not-panic-safe-6.stderr
index a4c75ec..2cd7805 100644
--- a/src/test/ui/not-panic/not-panic-safe-6.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-6.stderr
@@ -1,21 +1,22 @@
 error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-6.rs:9:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<*mut RefCell<i32>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `std::cell::RefCell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
    = note: required because it appears within the type `std::cell::RefCell<i32>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*mut std::cell::RefCell<i32>`
-note: required by `assert`
-  --> $DIR/not-panic-safe-6.rs:6:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the type `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> $DIR/not-panic-safe-6.rs:9:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<*mut RefCell<i32>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
@@ -23,11 +24,6 @@
    = note: required because it appears within the type `std::cell::Cell<isize>`
    = note: required because it appears within the type `std::cell::RefCell<i32>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `*mut std::cell::RefCell<i32>`
-note: required by `assert`
-  --> $DIR/not-panic-safe-6.rs:6:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/not-panic/not-panic-safe.stderr b/src/test/ui/not-panic/not-panic-safe.stderr
index 2d12e69..315ea17 100644
--- a/src/test/ui/not-panic/not-panic-safe.stderr
+++ b/src/test/ui/not-panic/not-panic-safe.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary
   --> $DIR/not-panic-safe.rs:9:5
    |
+LL | fn assert<T: UnwindSafe + ?Sized>() {}
+   | ----------------------------------- required by `assert`
+...
 LL |     assert::<&mut i32>();
    |     ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary
    |
    = help: the trait `std::panic::UnwindSafe` is not implemented for `&mut i32`
-note: required by `assert`
-  --> $DIR/not-panic-safe.rs:6:1
-   |
-LL | fn assert<T: UnwindSafe + ?Sized>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/not-sync.stderr b/src/test/ui/not-sync.stderr
index d102528..57f1122 100644
--- a/src/test/ui/not-sync.stderr
+++ b/src/test/ui/not-sync.stderr
@@ -1,80 +1,68 @@
 error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
   --> $DIR/not-sync.rs:8:5
    |
+LL | fn test<T: Sync>() {}
+   | ------------------ required by `test`
+...
 LL |     test::<Cell<i32>>();
    |     ^^^^^^^^^^^^^^^^^ `std::cell::Cell<i32>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
-note: required by `test`
-  --> $DIR/not-sync.rs:5:1
-   |
-LL | fn test<T: Sync>() {}
-   | ^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::cell::RefCell<i32>` cannot be shared between threads safely
   --> $DIR/not-sync.rs:10:5
    |
+LL | fn test<T: Sync>() {}
+   | ------------------ required by `test`
+...
 LL |     test::<RefCell<i32>>();
    |     ^^^^^^^^^^^^^^^^^^^^ `std::cell::RefCell<i32>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>`
-note: required by `test`
-  --> $DIR/not-sync.rs:5:1
-   |
-LL | fn test<T: Sync>() {}
-   | ^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::rc::Rc<i32>` cannot be shared between threads safely
   --> $DIR/not-sync.rs:13:5
    |
+LL | fn test<T: Sync>() {}
+   | ------------------ required by `test`
+...
 LL |     test::<Rc<i32>>();
    |     ^^^^^^^^^^^^^^^ `std::rc::Rc<i32>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc<i32>`
-note: required by `test`
-  --> $DIR/not-sync.rs:5:1
-   |
-LL | fn test<T: Sync>() {}
-   | ^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::rc::Weak<i32>` cannot be shared between threads safely
   --> $DIR/not-sync.rs:15:5
    |
+LL | fn test<T: Sync>() {}
+   | ------------------ required by `test`
+...
 LL |     test::<Weak<i32>>();
    |     ^^^^^^^^^^^^^^^^^ `std::rc::Weak<i32>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::rc::Weak<i32>`
-note: required by `test`
-  --> $DIR/not-sync.rs:5:1
-   |
-LL | fn test<T: Sync>() {}
-   | ^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::sync::mpsc::Receiver<i32>` cannot be shared between threads safely
   --> $DIR/not-sync.rs:18:5
    |
+LL | fn test<T: Sync>() {}
+   | ------------------ required by `test`
+...
 LL |     test::<Receiver<i32>>();
    |     ^^^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<i32>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver<i32>`
-note: required by `test`
-  --> $DIR/not-sync.rs:5:1
-   |
-LL | fn test<T: Sync>() {}
-   | ^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::sync::mpsc::Sender<i32>` cannot be shared between threads safely
   --> $DIR/not-sync.rs:20:5
    |
+LL | fn test<T: Sync>() {}
+   | ------------------ required by `test`
+...
 LL |     test::<Sender<i32>>();
    |     ^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Sender<i32>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<i32>`
-note: required by `test`
-  --> $DIR/not-sync.rs:5:1
-   |
-LL | fn test<T: Sync>() {}
-   | ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/object-does-not-impl-trait.stderr b/src/test/ui/object-does-not-impl-trait.stderr
index 288ce96..d3add63 100644
--- a/src/test/ui/object-does-not-impl-trait.stderr
+++ b/src/test/ui/object-does-not-impl-trait.stderr
@@ -1,14 +1,10 @@
 error[E0277]: the trait bound `std::boxed::Box<dyn Foo>: Foo` is not satisfied
   --> $DIR/object-does-not-impl-trait.rs:6:35
    |
+LL | fn take_foo<F:Foo>(f: F) {}
+   | ------------------------ required by `take_foo`
 LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
    |                                   ^^^^^^^^ the trait `Foo` is not implemented for `std::boxed::Box<dyn Foo>`
-   |
-note: required by `take_foo`
-  --> $DIR/object-does-not-impl-trait.rs:5:1
-   |
-LL | fn take_foo<F:Foo>(f: F) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr
index 0c7e4e9..2df628e 100644
--- a/src/test/ui/object-pointer-types.stderr
+++ b/src/test/ui/object-pointer-types.stderr
@@ -2,7 +2,7 @@
   --> $DIR/object-pointer-types.rs:11:7
    |
 LL |     x.owned();
-   |       ^^^^^
+   |       ^^^^^ method not found in `&dyn Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `owned`, perhaps you need to implement it:
@@ -12,7 +12,7 @@
   --> $DIR/object-pointer-types.rs:17:7
    |
 LL |     x.owned();
-   |       ^^^^^
+   |       ^^^^^ method not found in `&mut dyn Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `owned`, perhaps you need to implement it:
@@ -22,7 +22,7 @@
   --> $DIR/object-pointer-types.rs:23:7
    |
 LL |     x.managed();
-   |       ^^^^^^^
+   |       ^^^^^^^ method not found in `std::boxed::Box<(dyn Foo + 'static)>`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/object-safety/object-safety-associated-consts.stderr b/src/test/ui/object-safety/object-safety-associated-consts.stderr
index 55f9e3f..7d5aa00 100644
--- a/src/test/ui/object-safety/object-safety-associated-consts.stderr
+++ b/src/test/ui/object-safety/object-safety-associated-consts.stderr
@@ -1,10 +1,11 @@
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/object-safety-associated-consts.rs:9:1
    |
+LL |     const X: usize;
+   |           - the trait cannot contain associated consts like `X`
+...
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
-   |
-   = note: the trait cannot contain associated consts like `X`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-safety/object-safety-generics.stderr b/src/test/ui/object-safety/object-safety-generics.stderr
index d66cdb98..b25e005 100644
--- a/src/test/ui/object-safety/object-safety-generics.stderr
+++ b/src/test/ui/object-safety/object-safety-generics.stderr
@@ -1,18 +1,20 @@
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/object-safety-generics.rs:14:1
    |
+LL |     fn bar<T>(&self, t: T);
+   |        --- method `bar` has generic type parameters
+...
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
-   |
-   = note: method `bar` has generic type parameters
 
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/object-safety-generics.rs:19:1
    |
+LL |     fn bar<T>(&self, t: T);
+   |        --- method `bar` has generic type parameters
+...
 LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
-   |
-   = note: method `bar` has generic type parameters
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.stderr
index c0c471c..971e79c 100644
--- a/src/test/ui/object-safety/object-safety-mentions-Self.stderr
+++ b/src/test/ui/object-safety/object-safety-mentions-Self.stderr
@@ -1,18 +1,20 @@
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/object-safety-mentions-Self.rs:17:1
    |
+LL |     fn bar(&self, x: &Self);
+   |        --- method `bar` references the `Self` type in its parameters or return type
+...
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
-   |
-   = note: method `bar` references the `Self` type in its arguments or return type
 
 error[E0038]: the trait `Baz` cannot be made into an object
   --> $DIR/object-safety-mentions-Self.rs:22:1
    |
+LL |     fn bar(&self) -> Self;
+   |        --- method `bar` references the `Self` type in its parameters or return type
+...
 LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object
-   |
-   = note: method `bar` references the `Self` type in its arguments or return type
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/object-safety/object-safety-no-static.stderr b/src/test/ui/object-safety/object-safety-no-static.stderr
index da8dd65..0de783f 100644
--- a/src/test/ui/object-safety/object-safety-no-static.stderr
+++ b/src/test/ui/object-safety/object-safety-no-static.stderr
@@ -1,10 +1,11 @@
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/object-safety-no-static.rs:8:1
    |
+LL |     fn foo();
+   |        --- associated function `foo` has no `self` parameter
+...
 LL | fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<dyn Foo + 'static> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
-   |
-   = note: method `foo` has no receiver
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr
index 5d5db21..b286265 100644
--- a/src/test/ui/on-unimplemented/multiple-impls.stderr
+++ b/src/test/ui/on-unimplemented/multiple-impls.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/multiple-impls.rs:33:5
    |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     --------------------------------------------- required by `Index::index`
+...
 LL |     Index::index(&[] as &[i32], 2u32);
    |     ^^^^^^^^^^^^ trait message
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
-note: required by `Index::index`
-  --> $DIR/multiple-impls.rs:12:5
-   |
-LL |     fn index(&self, index: Idx) -> &Self::Output;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/multiple-impls.rs:33:5
@@ -22,15 +20,13 @@
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:36:5
    |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     --------------------------------------------- required by `Index::index`
+...
 LL |     Index::index(&[] as &[i32], Foo(2u32));
    |     ^^^^^^^^^^^^ on impl for Foo
    |
    = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
-note: required by `Index::index`
-  --> $DIR/multiple-impls.rs:12:5
-   |
-LL |     fn index(&self, index: Idx) -> &Self::Output;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:36:5
@@ -43,15 +39,13 @@
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:39:5
    |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     --------------------------------------------- required by `Index::index`
+...
 LL |     Index::index(&[] as &[i32], Bar(2u32));
    |     ^^^^^^^^^^^^ on impl for Bar
    |
    = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
-note: required by `Index::index`
-  --> $DIR/multiple-impls.rs:12:5
-   |
-LL |     fn index(&self, index: Idx) -> &Self::Output;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:39:5
diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr
index 79cf22f..78dc9a5 100644
--- a/src/test/ui/on-unimplemented/on-impl.stderr
+++ b/src/test/ui/on-unimplemented/on-impl.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:5
    |
+LL |     fn index(&self, index: Idx) -> &Self::Output;
+   |     --------------------------------------------- required by `Index::index`
+...
 LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |     ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
-note: required by `Index::index`
-  --> $DIR/on-impl.rs:9:5
-   |
-LL |     fn index(&self, index: Idx) -> &Self::Output;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:5
diff --git a/src/test/ui/on-unimplemented/on-trait.stderr b/src/test/ui/on-unimplemented/on-trait.stderr
index ece8dee..992f53b 100644
--- a/src/test/ui/on-unimplemented/on-trait.stderr
+++ b/src/test/ui/on-unimplemented/on-trait.stderr
@@ -1,28 +1,24 @@
 error[E0277]: the trait bound `std::option::Option<std::vec::Vec<u8>>: MyFromIterator<&u8>` is not satisfied
   --> $DIR/on-trait.rs:28:30
    |
+LL | fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
+   | -------------------------------------------------------------------- required by `collect`
+...
 LL |     let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
    |                              ^^^^^^^ a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
    |
    = help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>`
-note: required by `collect`
-  --> $DIR/on-trait.rs:22:1
-   |
-LL | fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::string::String: Bar::Foo<u8, _, u32>` is not satisfied
   --> $DIR/on-trait.rs:31:21
    |
+LL | fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
+   | ---------------------------------------------- required by `foobar`
+...
 LL |     let x: String = foobar();
    |                     ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo`
    |
    = help: the trait `Bar::Foo<u8, _, u32>` is not implemented for `std::string::String`
-note: required by `foobar`
-  --> $DIR/on-trait.rs:12:1
-   |
-LL | fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/or-patterns/already-bound-name.rs b/src/test/ui/or-patterns/already-bound-name.rs
new file mode 100644
index 0000000..3ebf59c
--- /dev/null
+++ b/src/test/ui/or-patterns/already-bound-name.rs
@@ -0,0 +1,46 @@
+// This test ensures that the "already bound identifier in a product pattern"
+// correctly accounts for or-patterns.
+
+#![feature(or_patterns)]
+//~^ WARN the feature `or_patterns` is incomplete
+
+enum E<T> { A(T, T), B(T) }
+
+use E::*;
+
+fn main() {
+    let (a, a) = (0, 1); // Standard duplication without an or-pattern.
+    //~^ ERROR identifier `a` is bound more than once in the same pattern
+
+    let (a, A(a, _) | B(a)) = (0, A(1, 2));
+    //~^ ERROR identifier `a` is bound more than once in the same pattern
+    //~| ERROR identifier `a` is bound more than once in the same pattern
+
+    let (A(a, _) | B(a), a) = (A(0, 1), 2);
+    //~^ ERROR identifier `a` is bound more than once in the same pattern
+
+    let A(a, a) | B(a) = A(0, 1);
+    //~^ ERROR identifier `a` is bound more than once in the same pattern
+
+    let B(a) | A(a, a) = A(0, 1);
+    //~^ ERROR identifier `a` is bound more than once in the same pattern
+
+    match A(0, 1) {
+        B(a) | A(a, a) => {} // Let's ensure `match` has no funny business.
+        //~^ ERROR identifier `a` is bound more than once in the same pattern
+    }
+
+    let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
+    //~^ ERROR identifier `a` is bound more than once in the same pattern
+    //~| ERROR identifier `a` is bound more than once in the same pattern
+    //~| ERROR mismatched types
+
+    let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
+    //~^ ERROR identifier `a` is bound more than once in the same pattern
+    //~| ERROR identifier `a` is bound more than once in the same pattern
+    //~| ERROR variable `a` is not bound in all patterns
+
+    let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
+    //~^ ERROR identifier `a` is bound more than once in the same pattern
+    //~| ERROR identifier `a` is bound more than once in the same pattern
+}
diff --git a/src/test/ui/or-patterns/already-bound-name.stderr b/src/test/ui/or-patterns/already-bound-name.stderr
new file mode 100644
index 0000000..360699a
--- /dev/null
+++ b/src/test/ui/or-patterns/already-bound-name.stderr
@@ -0,0 +1,105 @@
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:12:13
+   |
+LL |     let (a, a) = (0, 1); // Standard duplication without an or-pattern.
+   |             ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:15:15
+   |
+LL |     let (a, A(a, _) | B(a)) = (0, A(1, 2));
+   |               ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:15:25
+   |
+LL |     let (a, A(a, _) | B(a)) = (0, A(1, 2));
+   |                         ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:19:26
+   |
+LL |     let (A(a, _) | B(a), a) = (A(0, 1), 2);
+   |                          ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:22:14
+   |
+LL |     let A(a, a) | B(a) = A(0, 1);
+   |              ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:25:21
+   |
+LL |     let B(a) | A(a, a) = A(0, 1);
+   |                     ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:29:21
+   |
+LL |         B(a) | A(a, a) => {} // Let's ensure `match` has no funny business.
+   |                     ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:33:36
+   |
+LL |     let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
+   |                                    ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:33:46
+   |
+LL |     let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
+   |                                              ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:38:36
+   |
+LL |     let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
+   |                                    ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:38:46
+   |
+LL |     let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
+   |                                              ^ used in a pattern more than once
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/already-bound-name.rs:38:9
+   |
+LL |     let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
+   |         ^^^^ pattern doesn't bind `a`        - variable not in all patterns
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:43:49
+   |
+LL |     let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
+   |                                                 ^ used in a pattern more than once
+
+error[E0416]: identifier `a` is bound more than once in the same pattern
+  --> $DIR/already-bound-name.rs:43:59
+   |
+LL |     let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
+   |                                                           ^ used in a pattern more than once
+
+warning: the feature `or_patterns` is incomplete and may cause the compiler to crash
+  --> $DIR/already-bound-name.rs:4:12
+   |
+LL | #![feature(or_patterns)]
+   |            ^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/already-bound-name.rs:33:31
+   |
+LL |     let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
+   |                               ^ expected integer, found enum `E`
+   |
+   = note: expected type `{integer}`
+              found type `E<{integer}>`
+
+error: aborting due to 15 previous errors
+
+Some errors have detailed explanations: E0308, E0408, E0416.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/or-patterns/consistent-bindings.rs b/src/test/ui/or-patterns/consistent-bindings.rs
new file mode 100644
index 0000000..0eb539d
--- /dev/null
+++ b/src/test/ui/or-patterns/consistent-bindings.rs
@@ -0,0 +1,46 @@
+// Check that or-patterns with consistent bindings across arms are allowed.
+
+// edition:2018
+
+#![feature(or_patterns)]
+//~^ WARN the feature `or_patterns` is incomplete
+
+fn main() {
+    // One level:
+    let Ok(a) | Err(a) = Ok(0);
+    let Ok(ref a) | Err(ref a) = Ok(0);
+    let Ok(ref mut a) | Err(ref mut a) = Ok(0);
+
+    // Two levels:
+    enum Tri<S, T, U> { V1(S), V2(T), V3(U) }
+    use Tri::*;
+
+    let Ok((V1(a) | V2(a) | V3(a), b)) | Err(Ok((a, b)) | Err((a, b)))
+        : Result<_, Result<_, _>>
+        = Ok((V1(1), 1));
+
+    let Ok((V1(a) | V2(a) | V3(a), ref b)) | Err(Ok((a, ref b)) | Err((a, ref b)))
+        : Result<_, Result<_, _>>
+        = Ok((V1(1), 1));
+
+    // Three levels:
+    let (
+            a,
+            Err((ref mut b, ref c, d)) |
+            Ok((
+                Ok(
+                    V1((ref c, d)) |
+                    V2((d, ref c)) |
+                    V3((ref c, Ok((_, d)) | Err((d, _))))
+                ) |
+                Err((ref c, d)),
+                ref mut b
+            ))
+        ) =
+        (1, Ok((Ok(V3((1, Ok((1, 1))))), 1)));
+
+    // FIXME(or_patterns; Centril | dlrobertson): remove this line below and
+    // change this test to check-pass once MIR can handle or-patterns with bindings.
+    let () = 0;
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/or-patterns/consistent-bindings.stderr b/src/test/ui/or-patterns/consistent-bindings.stderr
new file mode 100644
index 0000000..7f5e670
--- /dev/null
+++ b/src/test/ui/or-patterns/consistent-bindings.stderr
@@ -0,0 +1,20 @@
+warning: the feature `or_patterns` is incomplete and may cause the compiler to crash
+  --> $DIR/consistent-bindings.rs:5:12
+   |
+LL | #![feature(or_patterns)]
+   |            ^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/consistent-bindings.rs:44:9
+   |
+LL |     let () = 0;
+   |         ^^ expected integer, found ()
+   |
+   = note: expected type `{integer}`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/or-patterns/inconsistent-modes.rs b/src/test/ui/or-patterns/inconsistent-modes.rs
new file mode 100644
index 0000000..4483689
--- /dev/null
+++ b/src/test/ui/or-patterns/inconsistent-modes.rs
@@ -0,0 +1,28 @@
+// This test ensures that or patterns require binding mode consistency across arms.
+
+#![feature(or_patterns)]
+//~^ WARN the feature `or_patterns` is incomplete
+
+#![allow(non_camel_case_types)]
+fn main() {
+    // One level:
+    let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0);
+    //~^ ERROR variable `a` is bound in inconsistent ways
+    let Ok(ref mut a) | Err(a): Result<u8, &mut u8> = Ok(0);
+    //~^ ERROR variable `a` is bound in inconsistent ways
+    let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
+    //~^ ERROR variable `a` is bound in inconsistent ways
+    //~| ERROR mismatched types
+    let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
+    //~^ ERROR variable `a` is bound in inconsistent ways
+    //~| ERROR variable `b` is bound in inconsistent ways
+    //~| ERROR mismatched types
+
+    // Two levels:
+    let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0);
+    //~^ ERROR variable `a` is bound in inconsistent ways
+
+    // Three levels:
+    let Ok([ Ok((Ok(ref a) | Err(a),)) | Err(a) ]) | Err(a) = Err(&1);
+    //~^ ERROR variable `a` is bound in inconsistent ways
+}
diff --git a/src/test/ui/or-patterns/inconsistent-modes.stderr b/src/test/ui/or-patterns/inconsistent-modes.stderr
new file mode 100644
index 0000000..0a36ed5
--- /dev/null
+++ b/src/test/ui/or-patterns/inconsistent-modes.stderr
@@ -0,0 +1,80 @@
+error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+  --> $DIR/inconsistent-modes.rs:9:25
+   |
+LL |     let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0);
+   |            -            ^ bound in different ways
+   |            |
+   |            first binding
+
+error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+  --> $DIR/inconsistent-modes.rs:11:29
+   |
+LL |     let Ok(ref mut a) | Err(a): Result<u8, &mut u8> = Ok(0);
+   |                    -        ^ bound in different ways
+   |                    |
+   |                    first binding
+
+error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+  --> $DIR/inconsistent-modes.rs:13:33
+   |
+LL |     let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
+   |                - first binding  ^ bound in different ways
+
+error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+  --> $DIR/inconsistent-modes.rs:16:39
+   |
+LL |     let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
+   |                 - first binding       ^ bound in different ways
+
+error[E0409]: variable `b` is bound in inconsistent ways within the same match arm
+  --> $DIR/inconsistent-modes.rs:16:46
+   |
+LL |     let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
+   |                    - first binding           ^ bound in different ways
+
+error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+  --> $DIR/inconsistent-modes.rs:22:38
+   |
+LL |     let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0);
+   |                        -             ^ bound in different ways
+   |                        |
+   |                        first binding
+
+error[E0409]: variable `a` is bound in inconsistent ways within the same match arm
+  --> $DIR/inconsistent-modes.rs:26:34
+   |
+LL |     let Ok([ Ok((Ok(ref a) | Err(a),)) | Err(a) ]) | Err(a) = Err(&1);
+   |                         -        ^ bound in different ways
+   |                         |
+   |                         first binding
+
+warning: the feature `or_patterns` is incomplete and may cause the compiler to crash
+  --> $DIR/inconsistent-modes.rs:3:12
+   |
+LL | #![feature(or_patterns)]
+   |            ^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/inconsistent-modes.rs:13:25
+   |
+LL |     let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
+   |                         ^^^^^^^^^ types differ in mutability
+   |
+   = note: expected type `&&u8`
+              found type `&mut &mut u8`
+
+error[E0308]: mismatched types
+  --> $DIR/inconsistent-modes.rs:16:31
+   |
+LL |     let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
+   |                               ^^^^^^^^^ types differ in mutability
+   |
+   = note: expected type `&{integer}`
+              found type `&mut _`
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0308, E0409.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/or-patterns/missing-bindings.rs b/src/test/ui/or-patterns/missing-bindings.rs
new file mode 100644
index 0000000..b065028
--- /dev/null
+++ b/src/test/ui/or-patterns/missing-bindings.rs
@@ -0,0 +1,84 @@
+// This test ensures that or patterns do not allow missing bindings in any of the arms.
+
+// edition:2018
+
+#![feature(or_patterns)]
+//~^ WARN the feature `or_patterns` is incomplete
+
+#![allow(non_camel_case_types)]
+
+fn main() {}
+
+fn check_handling_of_paths() {
+    mod bar {
+        pub enum foo {
+            alpha,
+            beta,
+            charlie
+        }
+    }
+
+    use bar::foo::{alpha, charlie};
+    let alpha | beta | charlie = alpha; //~  ERROR variable `beta` is not bound in all patterns
+    match Some(alpha) {
+        Some(alpha | beta) => {} //~ ERROR variable `beta` is not bound in all patterns
+    }
+}
+
+fn check_misc_nesting() {
+    enum E<T> { A(T, T), B(T) }
+    use E::*;
+    enum Vars3<S, T, U> { V1(S), V2(T), V3(U) }
+    use Vars3::*;
+
+    // One level:
+    const X: E<u8> = B(0);
+    let A(a, _) | _ = X; //~ ERROR variable `a` is not bound in all patterns
+    let _ | B(a) = X; //~ ERROR variable `a` is not bound in all patterns
+    let A(..) | B(a) = X; //~ ERROR variable `a` is not bound in all patterns
+    let A(a, _) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns
+    let A(_, a) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns
+    let A(a, b) | B(a) = X; //~ ERROR variable `b` is not bound in all patterns
+
+    // Two levels:
+    const Y: E<E<u8>> = B(B(0));
+    let A(A(..) | B(_), _) | B(a) = Y; //~ ERROR variable `a` is not bound in all patterns
+    let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y;
+    //~^ ERROR variable `a` is not bound in all patterns
+    let A(A(a, b) | B(c), d) | B(e) = Y;
+    //~^ ERROR variable `a` is not bound in all patterns
+    //~| ERROR variable `a` is not bound in all patterns
+    //~| ERROR variable `b` is not bound in all patterns
+    //~| ERROR variable `b` is not bound in all patterns
+    //~| ERROR variable `c` is not bound in all patterns
+    //~| ERROR variable `c` is not bound in all patterns
+    //~| ERROR variable `d` is not bound in all patterns
+    //~| ERROR variable `e` is not bound in all patterns
+
+    // Three levels:
+    let (
+            V1(
+            //~^ ERROR variable `b` is not bound in all patterns
+            //~| ERROR variable `c` is not bound in all patterns
+                A(
+                    Ok(a) | Err(_), //~ ERROR variable `a` is not bound in all patterns
+                    _
+                ) |
+                B(Ok(a) | Err(a))
+            ) |
+            V2(
+                A(
+                    A(_, a) | //~ ERROR variable `b` is not bound in all patterns
+                    B(b), //~ ERROR variable `a` is not bound in all patterns
+                    _
+                ) |
+                B(_)
+                //~^ ERROR variable `a` is not bound in all patterns
+                //~| ERROR variable `b` is not bound in all patterns
+            ) |
+            V3(c),
+            //~^ ERROR variable `a` is not bound in all patterns
+        )
+        : (Vars3<E<Result<u8, u8>>, E<E<u8>>, u8>,)
+        = (V3(0),);
+}
diff --git a/src/test/ui/or-patterns/missing-bindings.stderr b/src/test/ui/or-patterns/missing-bindings.stderr
new file mode 100644
index 0000000..c73af7a
--- /dev/null
+++ b/src/test/ui/or-patterns/missing-bindings.stderr
@@ -0,0 +1,250 @@
+error[E0408]: variable `beta` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:22:9
+   |
+LL |     let alpha | beta | charlie = alpha;
+   |         ^^^^^   ----   ^^^^^^^ pattern doesn't bind `beta`
+   |         |       |
+   |         |       variable not in all patterns
+   |         pattern doesn't bind `beta`
+
+error[E0408]: variable `beta` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:24:14
+   |
+LL |         Some(alpha | beta) => {}
+   |              ^^^^^   ---- variable not in all patterns
+   |              |
+   |              pattern doesn't bind `beta`
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:36:19
+   |
+LL |     let A(a, _) | _ = X;
+   |           -       ^ pattern doesn't bind `a`
+   |           |
+   |           variable not in all patterns
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:37:9
+   |
+LL |     let _ | B(a) = X;
+   |         ^     - variable not in all patterns
+   |         |
+   |         pattern doesn't bind `a`
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:38:9
+   |
+LL |     let A(..) | B(a) = X;
+   |         ^^^^^     - variable not in all patterns
+   |         |
+   |         pattern doesn't bind `a`
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:39:19
+   |
+LL |     let A(a, _) | B(_) = X;
+   |           -       ^^^^ pattern doesn't bind `a`
+   |           |
+   |           variable not in all patterns
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:40:19
+   |
+LL |     let A(_, a) | B(_) = X;
+   |              -    ^^^^ pattern doesn't bind `a`
+   |              |
+   |              variable not in all patterns
+
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:41:19
+   |
+LL |     let A(a, b) | B(a) = X;
+   |              -    ^^^^ pattern doesn't bind `b`
+   |              |
+   |              variable not in all patterns
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:45:9
+   |
+LL |     let A(A(..) | B(_), _) | B(a) = Y;
+   |         ^^^^^^^^^^^^^^^^^^     - variable not in all patterns
+   |         |
+   |         pattern doesn't bind `a`
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:46:11
+   |
+LL |     let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y;
+   |           ^^^^^     - variable not in all patterns
+   |           |
+   |           pattern doesn't bind `a`
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:48:21
+   |
+LL |     let A(A(a, b) | B(c), d) | B(e) = Y;
+   |             -       ^^^^ pattern doesn't bind `a`
+   |             |
+   |             variable not in all patterns
+
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:48:21
+   |
+LL |     let A(A(a, b) | B(c), d) | B(e) = Y;
+   |                -    ^^^^ pattern doesn't bind `b`
+   |                |
+   |                variable not in all patterns
+
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:48:11
+   |
+LL |     let A(A(a, b) | B(c), d) | B(e) = Y;
+   |           ^^^^^^^     - variable not in all patterns
+   |           |
+   |           pattern doesn't bind `c`
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:48:32
+   |
+LL |     let A(A(a, b) | B(c), d) | B(e) = Y;
+   |             -                  ^^^^ pattern doesn't bind `a`
+   |             |
+   |             variable not in all patterns
+
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:48:32
+   |
+LL |     let A(A(a, b) | B(c), d) | B(e) = Y;
+   |                -               ^^^^ pattern doesn't bind `b`
+   |                |
+   |                variable not in all patterns
+
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:48:32
+   |
+LL |     let A(A(a, b) | B(c), d) | B(e) = Y;
+   |                       -        ^^^^ pattern doesn't bind `c`
+   |                       |
+   |                       variable not in all patterns
+
+error[E0408]: variable `d` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:48:32
+   |
+LL |     let A(A(a, b) | B(c), d) | B(e) = Y;
+   |                           -    ^^^^ pattern doesn't bind `d`
+   |                           |
+   |                           variable not in all patterns
+
+error[E0408]: variable `e` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:48:9
+   |
+LL |     let A(A(a, b) | B(c), d) | B(e) = Y;
+   |         ^^^^^^^^^^^^^^^^^^^^     - variable not in all patterns
+   |         |
+   |         pattern doesn't bind `e`
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:64:29
+   |
+LL |                     Ok(a) | Err(_),
+   |                        -    ^^^^^^ pattern doesn't bind `a`
+   |                        |
+   |                        variable not in all patterns
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:72:21
+   |
+LL |                     A(_, a) |
+   |                          - variable not in all patterns
+LL |                     B(b),
+   |                     ^^^^ pattern doesn't bind `a`
+
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:71:21
+   |
+LL |                     A(_, a) |
+   |                     ^^^^^^^ pattern doesn't bind `b`
+LL |                     B(b),
+   |                       - variable not in all patterns
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:75:17
+   |
+LL |                     A(_, a) |
+   |                          - variable not in all patterns
+...
+LL |                 B(_)
+   |                 ^^^^ pattern doesn't bind `a`
+
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:75:17
+   |
+LL |                     B(b),
+   |                       - variable not in all patterns
+...
+LL |                 B(_)
+   |                 ^^^^ pattern doesn't bind `b`
+
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:79:13
+   |
+LL |                 B(Ok(a) | Err(a))
+   |                               - variable not in all patterns
+...
+LL |                     A(_, a) |
+   |                          - variable not in all patterns
+...
+LL |             V3(c),
+   |             ^^^^^ pattern doesn't bind `a`
+
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:60:13
+   |
+LL | /             V1(
+LL | |
+LL | |
+LL | |                 A(
+...  |
+LL | |                 B(Ok(a) | Err(a))
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `b`
+...
+LL |                       B(b),
+   |                         - variable not in all patterns
+...
+LL |               V3(c),
+   |               ^^^^^ pattern doesn't bind `b`
+
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:60:13
+   |
+LL | /             V1(
+LL | |
+LL | |
+LL | |                 A(
+...  |
+LL | |                 B(Ok(a) | Err(a))
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `c`
+LL | /             V2(
+LL | |                 A(
+LL | |                     A(_, a) |
+LL | |                     B(b),
+...  |
+LL | |
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `c`
+LL |               V3(c),
+   |                  - variable not in all patterns
+
+warning: the feature `or_patterns` is incomplete and may cause the compiler to crash
+  --> $DIR/missing-bindings.rs:5:12
+   |
+LL | #![feature(or_patterns)]
+   |            ^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 26 previous errors
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/overlap-marker-trait.stderr b/src/test/ui/overlap-marker-trait.stderr
index a59af8d..a66e399 100644
--- a/src/test/ui/overlap-marker-trait.stderr
+++ b/src/test/ui/overlap-marker-trait.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied
   --> $DIR/overlap-marker-trait.rs:30:5
    |
+LL | fn is_marker<T: Marker>() { }
+   | ------------------------- required by `is_marker`
+...
 LL |     is_marker::<NotDebugOrDisplay>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay`
-   |
-note: required by `is_marker`
-  --> $DIR/overlap-marker-trait.rs:18:1
-   |
-LL | fn is_marker<T: Marker>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser-recovery-1.rs b/src/test/ui/parser-recovery-1.rs
index 21d3604..8126525 100644
--- a/src/test/ui/parser-recovery-1.rs
+++ b/src/test/ui/parser-recovery-1.rs
@@ -3,6 +3,7 @@
 // Test that we can recover from missing braces in the parser.
 
 trait Foo {
+//~^ ERROR `main` function not found
     fn bar() {
         let x = foo();
         //~^ ERROR cannot find function `foo` in this scope
diff --git a/src/test/ui/parser-recovery-1.stderr b/src/test/ui/parser-recovery-1.stderr
index c29f427..ffe2b33 100644
--- a/src/test/ui/parser-recovery-1.stderr
+++ b/src/test/ui/parser-recovery-1.stderr
@@ -1,8 +1,9 @@
 error: this file contains an un-closed delimiter
-  --> $DIR/parser-recovery-1.rs:15:55
+  --> $DIR/parser-recovery-1.rs:16:55
    |
 LL | trait Foo {
    |           - un-closed delimiter
+LL |
 LL |     fn bar() {
    |              - this delimiter might not be properly closed...
 ...
@@ -13,26 +14,34 @@
    |                                                       ^
 
 error: unexpected token: `;`
-  --> $DIR/parser-recovery-1.rs:12:15
+  --> $DIR/parser-recovery-1.rs:13:15
    |
 LL |     let x = y.;
    |               ^
 
 error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/parser-recovery-1.rs:7:17
+  --> $DIR/parser-recovery-1.rs:8:17
    |
 LL |         let x = foo();
    |                 ^^^ not found in this scope
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/parser-recovery-1.rs:12:13
+  --> $DIR/parser-recovery-1.rs:13:13
    |
 LL |     let x = y.;
    |             ^ not found in this scope
 
 error[E0601]: `main` function not found in crate `parser_recovery_1`
+  --> $DIR/parser-recovery-1.rs:5:1
    |
-   = note: consider adding a `main` function to `$DIR/parser-recovery-1.rs`
+LL | / trait Foo {
+LL | |
+LL | |     fn bar() {
+LL | |         let x = foo();
+...  |
+LL | |
+LL | | }
+   | |______________________________________________________^ consider adding a `main` function to `$DIR/parser-recovery-1.rs`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/parser/do-catch-suggests-try.rs b/src/test/ui/parser/do-catch-suggests-try.rs
index 61fae72..d805ab7 100644
--- a/src/test/ui/parser/do-catch-suggests-try.rs
+++ b/src/test/ui/parser/do-catch-suggests-try.rs
@@ -1,5 +1,5 @@
 fn main() {
     let _: Option<()> = do catch {};
     //~^ ERROR found removed `do catch` syntax
-    //~^^ HELP Following RFC #2388, the new non-placeholder syntax is `try`
+    //~^^ HELP following RFC #2388, the new non-placeholder syntax is `try`
 }
diff --git a/src/test/ui/parser/do-catch-suggests-try.stderr b/src/test/ui/parser/do-catch-suggests-try.stderr
index 6d13b0f..e151d4c 100644
--- a/src/test/ui/parser/do-catch-suggests-try.stderr
+++ b/src/test/ui/parser/do-catch-suggests-try.stderr
@@ -4,7 +4,7 @@
 LL |     let _: Option<()> = do catch {};
    |                         ^^
    |
-   = help: Following RFC #2388, the new non-placeholder syntax is `try`
+   = help: following RFC #2388, the new non-placeholder syntax is `try`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-2354.rs b/src/test/ui/parser/issue-2354.rs
index 565f848..a14eb6e 100644
--- a/src/test/ui/parser/issue-2354.rs
+++ b/src/test/ui/parser/issue-2354.rs
@@ -1,4 +1,7 @@
 fn foo() { //~ NOTE un-closed delimiter
+//~^ ERROR `main` function not found
+//~^^ NOTE main function must be defined
+//~^^^ NOTE you have one or more functions
   match Some(10) {
   //~^ NOTE this delimiter might not be properly closed...
       Some(y) => { panic!(); }
@@ -11,5 +14,5 @@
     while (i < 1000) {}
 }
 
-fn main() {} //~ NOTE here is a function named 'main'
+fn main() {} //~ NOTE here is a function named `main`
              //~ ERROR this file contains an un-closed delimiter
diff --git a/src/test/ui/parser/issue-2354.stderr b/src/test/ui/parser/issue-2354.stderr
index 7098da7..038e3dc 100644
--- a/src/test/ui/parser/issue-2354.stderr
+++ b/src/test/ui/parser/issue-2354.stderr
@@ -1,8 +1,9 @@
 error: this file contains an un-closed delimiter
-  --> $DIR/issue-2354.rs:15:66
+  --> $DIR/issue-2354.rs:18:66
    |
 LL | fn foo() {
    |          - un-closed delimiter
+...
 LL |   match Some(10) {
    |                  - this delimiter might not be properly closed...
 ...
@@ -13,13 +14,24 @@
    |                                                                  ^
 
 error[E0601]: `main` function not found in crate `issue_2354`
+  --> $DIR/issue-2354.rs:1:1
    |
-   = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior.
-note: here is a function named 'main'
-  --> $DIR/issue-2354.rs:14:1
+LL | / fn foo() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | | fn main() {}
+LL | |
+   | |_________________________________________________________________^ the main function must be defined at the crate level (in `$DIR/issue-2354.rs`)
+   |
+note: here is a function named `main`
+  --> $DIR/issue-2354.rs:17:1
    |
 LL | fn main() {}
    | ^^^^^^^^^^^^
+   = note: you have one or more functions named `main` not defined at the crate level
+   = help: either move the `main` function definitions or attach the `#[main]` attribute to one of them
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.rs b/src/test/ui/parser/lex-bad-char-literals-2.rs
index 1e180f8..d35dafd 100644
--- a/src/test/ui/parser/lex-bad-char-literals-2.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-2.rs
@@ -2,3 +2,5 @@
 static c: char =
     'nope' //~ ERROR: character literal may only contain one codepoint
 ;
+
+fn main() {}
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.stderr b/src/test/ui/parser/lex-bad-char-literals-2.stderr
index b0a4ed0..5653d4e 100644
--- a/src/test/ui/parser/lex-bad-char-literals-2.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-2.stderr
@@ -8,10 +8,5 @@
 LL |     "nope"
    |     ^^^^^^
 
-error[E0601]: `main` function not found in crate `lex_bad_char_literals_2`
-   |
-   = note: consider adding a `main` function to `$DIR/lex-bad-char-literals-2.rs`
+error: aborting due to previous error
 
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs
index 525be5d..3dcc0c8 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.rs
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs
@@ -11,8 +11,7 @@
     //~| ERROR: mismatched types
 
     f<X>();
-    //~^ ERROR: chained comparison operators require parentheses
-    //~| ERROR: binary operation `<` cannot be applied to type `fn() {f::<_>}`
+    //~^ ERROR chained comparison operators require parentheses
     //~| HELP: use `::<...>` instead of `<...>`
     //~| HELP: or use `(...)`
 }
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
index 76e548d..e927f4c 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
@@ -37,17 +37,6 @@
    = note: expected type `bool`
               found type `{integer}`
 
-error[E0369]: binary operation `<` cannot be applied to type `fn() {f::<_>}`
-  --> $DIR/require-parens-for-chained-comparison.rs:13:6
-   |
-LL |     f<X>();
-   |     -^- X
-   |     |
-   |     fn() {f::<_>}
-   |
-   = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() {f::<_>}`
+error: aborting due to 5 previous errors
 
-error: aborting due to 6 previous errors
-
-Some errors have detailed explanations: E0308, E0369.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/trait-object-lifetime-parens.rs b/src/test/ui/parser/trait-object-lifetime-parens.rs
index 5bbda42..c8b0eb6 100644
--- a/src/test/ui/parser/trait-object-lifetime-parens.rs
+++ b/src/test/ui/parser/trait-object-lifetime-parens.rs
@@ -9,7 +9,6 @@
     let _: Box<('a) + Trait>;
     //~^ ERROR expected type, found `'a`
     //~| ERROR expected `:`, found `)`
-    //~| ERROR chained comparison operators require parentheses
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr
index 7ffc26e..319a308 100644
--- a/src/test/ui/parser/trait-object-lifetime-parens.stderr
+++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr
@@ -16,15 +16,6 @@
 LL |     let _: Box<('a) + Trait>;
    |                   ^ expected `:`
 
-error: chained comparison operators require parentheses
-  --> $DIR/trait-object-lifetime-parens.rs:9:15
-   |
-LL |     let _: Box<('a) + Trait>;
-   |               ^^^^^^^^^^^^^^^
-   |
-   = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
-   = help: or use `(...)` if you meant to specify fn arguments
-
 error: expected type, found `'a`
   --> $DIR/trait-object-lifetime-parens.rs:9:17
    |
@@ -33,5 +24,5 @@
    |         |
    |         while parsing the type for `_`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr
index 633c63b..818f61b 100644
--- a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr
+++ b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr
@@ -1,5 +1,5 @@
 error: incorrect close delimiter: `}`
-  --> $DIR/unclosed_delim_mod.rs:5:1
+  --> $DIR/unclosed_delim_mod.rs:7:1
    |
 LL | pub fn new() -> Result<Value, ()> {
    |                                   - close delimiter possibly meant for this
diff --git a/src/test/ui/parser/unclosed_delim_mod.rs b/src/test/ui/parser/unclosed_delim_mod.rs
index b1664f4..486e233 100644
--- a/src/test/ui/parser/unclosed_delim_mod.rs
+++ b/src/test/ui/parser/unclosed_delim_mod.rs
@@ -1,3 +1,5 @@
+fn main() {}
+
 pub struct Value {}
 pub fn new() -> Result<Value, ()> {
     Ok(Value {
diff --git a/src/test/ui/parser/unclosed_delim_mod.stderr b/src/test/ui/parser/unclosed_delim_mod.stderr
index cc04eb5..fe2d968 100644
--- a/src/test/ui/parser/unclosed_delim_mod.stderr
+++ b/src/test/ui/parser/unclosed_delim_mod.stderr
@@ -1,5 +1,5 @@
 error: incorrect close delimiter: `}`
-  --> $DIR/unclosed_delim_mod.rs:5:1
+  --> $DIR/unclosed_delim_mod.rs:7:1
    |
 LL | pub fn new() -> Result<Value, ()> {
    |                                   - close delimiter possibly meant for this
@@ -9,10 +9,5 @@
 LL | }
    | ^ incorrect close delimiter
 
-error[E0601]: `main` function not found in crate `unclosed_delim_mod`
-   |
-   = note: consider adding a `main` function to `$DIR/unclosed_delim_mod.rs`
+error: aborting due to previous error
 
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr
index 0430897..e64b6ef 100644
--- a/src/test/ui/pattern/pat-tuple-overfield.stderr
+++ b/src/test/ui/pattern/pat-tuple-overfield.stderr
@@ -19,12 +19,18 @@
 error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
   --> $DIR/pat-tuple-overfield.rs:10:9
    |
+LL | struct S(u8, u8, u8);
+   | --------------------- tuple struct defined here
+...
 LL |         S(1, 2, 3, 4) => {}
    |         ^^^^^^^^^^^^^ expected 3 fields, found 4
 
 error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
   --> $DIR/pat-tuple-overfield.rs:12:9
    |
+LL | struct S(u8, u8, u8);
+   | --------------------- tuple struct defined here
+...
 LL |         S(1, 2, .., 3, 4) => {}
    |         ^^^^^^^^^^^^^^^^^ expected 3 fields, found 4
 
diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr
index a581f07..4fbc630 100644
--- a/src/test/ui/pattern/pattern-error-continue.stderr
+++ b/src/test/ui/pattern/pattern-error-continue.stderr
@@ -15,6 +15,9 @@
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
   --> $DIR/pattern-error-continue.rs:17:9
    |
+LL |     B(isize, isize),
+   |     --------------- tuple variant defined here
+...
 LL |         A::B(_, _, _) => (),
    |         ^^^^^^^^^^^^^ expected 2 fields, found 3
 
diff --git a/src/test/ui/phantom-oibit.stderr b/src/test/ui/phantom-oibit.stderr
index ec8b318..284102a 100644
--- a/src/test/ui/phantom-oibit.stderr
+++ b/src/test/ui/phantom-oibit.stderr
@@ -1,6 +1,9 @@
 error[E0277]: `T` cannot be shared between threads safely
   --> $DIR/phantom-oibit.rs:21:5
    |
+LL | fn is_zen<T: Zen>(_: T) {}
+   | ----------------------- required by `is_zen`
+...
 LL |     is_zen(x)
    |     ^^^^^^ `T` cannot be shared between threads safely
    |
@@ -9,15 +12,13 @@
    = note: required because of the requirements on the impl of `Zen` for `&T`
    = note: required because it appears within the type `std::marker::PhantomData<&T>`
    = note: required because it appears within the type `Guard<'_, T>`
-note: required by `is_zen`
-  --> $DIR/phantom-oibit.rs:18:1
-   |
-LL | fn is_zen<T: Zen>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `T` cannot be shared between threads safely
   --> $DIR/phantom-oibit.rs:26:5
    |
+LL | fn is_zen<T: Zen>(_: T) {}
+   | ----------------------- required by `is_zen`
+...
 LL |     is_zen(x)
    |     ^^^^^^ `T` cannot be shared between threads safely
    |
@@ -27,11 +28,6 @@
    = note: required because it appears within the type `std::marker::PhantomData<&T>`
    = note: required because it appears within the type `Guard<'_, T>`
    = note: required because it appears within the type `Nested<Guard<'_, T>>`
-note: required by `is_zen`
-  --> $DIR/phantom-oibit.rs:18:1
-   |
-LL | fn is_zen<T: Zen>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
index 95b4036..58109be 100644
--- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
@@ -17,10 +17,10 @@
 
 fn baz() -> impl std::fmt::Display {
     if false {
-    //~^ ERROR mismatched types
         return 0i32;
     } else {
         1u32
+        //~^ ERROR mismatched types
     }
 }
 
@@ -33,4 +33,33 @@
     }
 }
 
+fn bat() -> impl std::fmt::Display {
+    match 13 {
+        0 => return 0i32,
+        _ => 1u32,
+        //~^ ERROR mismatched types
+    }
+}
+
+fn can() -> impl std::fmt::Display {
+    match 13 {
+    //~^ ERROR mismatched types
+        0 => return 0i32,
+        1 => 1u32,
+        _ => 2u32,
+    }
+}
+
+fn cat() -> impl std::fmt::Display {
+    match 13 {
+        0 => {
+            return 0i32;
+        }
+        _ => {
+            1u32
+            //~^ ERROR mismatched types
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
index ee1e360..314ff84 100644
--- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -29,18 +29,16 @@
               found type `u32`
 
 error[E0308]: mismatched types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9
    |
-LL |   fn baz() -> impl std::fmt::Display {
-   |               ---------------------- expected because this return type...
-LL | /     if false {
-LL | |
-LL | |         return 0i32;
-   | |                ---- ...is found to be `i32` here
-LL | |     } else {
-LL | |         1u32
-LL | |     }
-   | |_____^ expected i32, found u32
+LL | fn baz() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     if false {
+LL |         return 0i32;
+   |                ---- ...is found to be `i32` here
+LL |     } else {
+LL |         1u32
+   |         ^^^^ expected i32, found u32
    |
    = note: expected type `i32`
               found type `u32`
@@ -61,6 +59,52 @@
    = note: expected type `i32`
               found type `u32`
 
-error: aborting due to 4 previous errors
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:39:14
+   |
+LL | fn bat() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     match 13 {
+LL |         0 => return 0i32,
+   |                     ---- ...is found to be `i32` here
+LL |         _ => 1u32,
+   |              ^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5
+   |
+LL |   fn can() -> impl std::fmt::Display {
+   |               ---------------------- expected because this return type...
+LL | /     match 13 {
+LL | |
+LL | |         0 => return 0i32,
+   | |                     ---- ...is found to be `i32` here
+LL | |         1 => 1u32,
+LL | |         _ => 2u32,
+LL | |     }
+   | |_____^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13
+   |
+LL | fn cat() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+...
+LL |             return 0i32;
+   |                    ---- ...is found to be `i32` here
+...
+LL |             1u32
+   |             ^^^^ expected i32, found u32
+   |
+   = note: expected type `i32`
+              found type `u32`
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/privacy/union-field-privacy-2.rs b/src/test/ui/privacy/union-field-privacy-2.rs
index 4827963..c2458f7 100644
--- a/src/test/ui/privacy/union-field-privacy-2.rs
+++ b/src/test/ui/privacy/union-field-privacy-2.rs
@@ -11,5 +11,5 @@
 
     let a = u.a; // OK
     let b = u.b; // OK
-    let c = u.c; //~ ERROR field `c` of struct `m::U` is private
+    let c = u.c; //~ ERROR field `c` of union `m::U` is private
 }
diff --git a/src/test/ui/privacy/union-field-privacy-2.stderr b/src/test/ui/privacy/union-field-privacy-2.stderr
index df054b8..8789178 100644
--- a/src/test/ui/privacy/union-field-privacy-2.stderr
+++ b/src/test/ui/privacy/union-field-privacy-2.stderr
@@ -1,4 +1,4 @@
-error[E0616]: field `c` of struct `m::U` is private
+error[E0616]: field `c` of union `m::U` is private
   --> $DIR/union-field-privacy-2.rs:14:13
    |
 LL |     let c = u.c;
diff --git a/src/test/ui/proc-macro/derive-still-gated.rs b/src/test/ui/proc-macro/derive-still-gated.rs
index 4e6f9b0..3f8d6f0 100644
--- a/src/test/ui/proc-macro/derive-still-gated.rs
+++ b/src/test/ui/proc-macro/derive-still-gated.rs
@@ -3,7 +3,7 @@
 #[macro_use]
 extern crate test_macros;
 
-#[derive_Empty] //~ ERROR cannot find attribute macro `derive_Empty` in this scope
+#[derive_Empty] //~ ERROR cannot find attribute `derive_Empty` in this scope
 struct A;
 
 fn main() {}
diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr
index 4df1715..99289fd 100644
--- a/src/test/ui/proc-macro/derive-still-gated.stderr
+++ b/src/test/ui/proc-macro/derive-still-gated.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `derive_Empty` in this scope
+error: cannot find attribute `derive_Empty` in this scope
   --> $DIR/derive-still-gated.rs:6:3
    |
 LL | #[derive_Empty]
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
index 0fe02a9..ea06f6c 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
@@ -2,40 +2,40 @@
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
         ],
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
@@ -43,39 +43,39 @@
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
         ],
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
 ]
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
index a499e13..7ee8078 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
+++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
@@ -3,55 +3,55 @@
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "identity",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: '!',
                 spacing: Alone,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "$crate",
-                        span: #2 bytes(LO..HI),
+                        span: #3 bytes(LO..HI),
                     },
                     Punct {
                         ch: ':',
                         spacing: Joint,
-                        span: #2 bytes(LO..HI),
+                        span: #3 bytes(LO..HI),
                     },
                     Punct {
                         ch: ':',
                         spacing: Alone,
-                        span: #2 bytes(LO..HI),
+                        span: #3 bytes(LO..HI),
                     },
                     Ident {
                         ident: "S",
-                        span: #2 bytes(LO..HI),
+                        span: #3 bytes(LO..HI),
                     },
                 ],
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
         ],
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S));
@@ -59,54 +59,54 @@
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #7 bytes(LO..HI),
+        span: #8 bytes(LO..HI),
     },
     Ident {
         ident: "B",
-        span: #7 bytes(LO..HI),
+        span: #8 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "identity",
-                span: #7 bytes(LO..HI),
+                span: #8 bytes(LO..HI),
             },
             Punct {
                 ch: '!',
                 spacing: Alone,
-                span: #7 bytes(LO..HI),
+                span: #8 bytes(LO..HI),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "$crate",
-                        span: #7 bytes(LO..HI),
+                        span: #8 bytes(LO..HI),
                     },
                     Punct {
                         ch: ':',
                         spacing: Joint,
-                        span: #7 bytes(LO..HI),
+                        span: #8 bytes(LO..HI),
                     },
                     Punct {
                         ch: ':',
                         spacing: Alone,
-                        span: #7 bytes(LO..HI),
+                        span: #8 bytes(LO..HI),
                     },
                     Ident {
                         ident: "S",
-                        span: #7 bytes(LO..HI),
+                        span: #8 bytes(LO..HI),
                     },
                 ],
-                span: #7 bytes(LO..HI),
+                span: #8 bytes(LO..HI),
             },
         ],
-        span: #7 bytes(LO..HI),
+        span: #8 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #7 bytes(LO..HI),
+        span: #8 bytes(LO..HI),
     },
 ]
diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout
index da1d754..4f7e000 100644
--- a/src/test/ui/proc-macro/dollar-crate.stdout
+++ b/src/test/ui/proc-macro/dollar-crate.stdout
@@ -2,40 +2,40 @@
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
         ],
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
@@ -43,40 +43,40 @@
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
         ],
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S);
@@ -84,80 +84,80 @@
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Ident {
         ident: "D",
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI),
+                span: #3 bytes(LO..HI),
             },
         ],
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI),
+        span: #3 bytes(LO..HI),
     },
 ]
 PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
         ],
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S);
@@ -165,40 +165,40 @@
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
         ],
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S);
@@ -206,39 +206,39 @@
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
     Ident {
         ident: "D",
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #9 bytes(LO..HI),
+                span: #10 bytes(LO..HI),
             },
         ],
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #9 bytes(LO..HI),
+        span: #10 bytes(LO..HI),
     },
 ]
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
index c9881ad..94a4b40 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
@@ -3,6 +3,11 @@
 // FIXME https://github.com/rust-lang/rust/issues/59998
 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
+// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
+// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
+// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
+// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
+// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
 
 #[macro_use]
 extern crate invalid_punct_ident;
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
index 40333a3..107f5fb 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/invalid-punct-ident-1.rs:10:1
+  --> $DIR/invalid-punct-ident-1.rs:15:1
    |
 LL | invalid_punct!();
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
index 15e2286..778b7ee 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
@@ -3,6 +3,11 @@
 // FIXME https://github.com/rust-lang/rust/issues/59998
 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
+// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
+// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
+// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
+// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
+// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
 
 #[macro_use]
 extern crate invalid_punct_ident;
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
index ec97e26..f1b9ecc 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/invalid-punct-ident-2.rs:10:1
+  --> $DIR/invalid-punct-ident-2.rs:15:1
    |
 LL | invalid_ident!();
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
index 629bbaa..f68ee3d 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
@@ -3,6 +3,11 @@
 // FIXME https://github.com/rust-lang/rust/issues/59998
 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
+// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
+// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
+// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
+// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
+// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
 
 #[macro_use]
 extern crate invalid_punct_ident;
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
index a5e5ded..6044b98 100644
--- a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
@@ -1,5 +1,5 @@
 error: proc macro panicked
-  --> $DIR/invalid-punct-ident-3.rs:10:1
+  --> $DIR/invalid-punct-ident-3.rs:15:1
    |
 LL | invalid_raw_ident!();
    | ^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
index 8a26df9..b17c056 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
@@ -25,17 +25,17 @@
     my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
 }
 fn check_bang2() {
-    my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr!` in this scope
+    my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr` in this scope
     crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines
                              //~| ERROR expected macro, found attribute macro `crate::my_macro_attr`
 }
 fn check_bang3() {
-    MyTrait!(); //~ ERROR cannot find macro `MyTrait!` in this scope
+    MyTrait!(); //~ ERROR cannot find macro `MyTrait` in this scope
     crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
                        //~| ERROR expected macro, found derive macro `crate::MyTrait`
 }
 
-#[my_macro] //~ ERROR cannot find attribute macro `my_macro` in this scope
+#[my_macro] //~ ERROR cannot find attribute `my_macro` in this scope
 #[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
                    //~| ERROR expected attribute, found macro `crate::my_macro`
 fn check_attr1() {}
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
index 0c863e9..c011a70 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -88,19 +88,19 @@
 LL | #[derive(crate::my_macro)]
    |          ^^^^^^^^^^^^^^^ not a derive macro
 
-error: cannot find macro `my_macro_attr!` in this scope
+error: cannot find macro `my_macro_attr` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:28:5
    |
 LL |     my_macro_attr!();
    |     ^^^^^^^^^^^^^
 
-error: cannot find macro `MyTrait!` in this scope
+error: cannot find macro `MyTrait` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:33:5
    |
 LL |     MyTrait!();
    |     ^^^^^^^
 
-error: cannot find attribute macro `my_macro` in this scope
+error: cannot find attribute `my_macro` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:38:3
    |
 LL | #[my_macro]
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs
index 0421522..6401522 100644
--- a/src/test/ui/proc-macro/proc-macro-attributes.rs
+++ b/src/test/ui/proc-macro/proc-macro-attributes.rs
@@ -4,7 +4,7 @@
 extern crate derive_b;
 
 #[B] //~ ERROR `B` is ambiguous
-#[C] //~ ERROR cannot find attribute macro `C` in this scope
+#[C] //~ ERROR cannot find attribute `C` in this scope
 #[B(D)] //~ ERROR `B` is ambiguous
 #[B(E = "foo")] //~ ERROR `B` is ambiguous
 #[B(arbitrary tokens)] //~ ERROR `B` is ambiguous
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr
index b068c6b..3ac93a7 100644
--- a/src/test/ui/proc-macro/proc-macro-attributes.stderr
+++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `C` in this scope
+error: cannot find attribute `C` in this scope
   --> $DIR/proc-macro-attributes.rs:7:3
    |
 LL | #[C]
diff --git a/src/test/ui/proc-macro/proc-macro-gates2.rs b/src/test/ui/proc-macro/proc-macro-gates2.rs
index 35d7fc8..2fd5efd 100644
--- a/src/test/ui/proc-macro/proc-macro-gates2.rs
+++ b/src/test/ui/proc-macro/proc-macro-gates2.rs
@@ -10,11 +10,11 @@
 // should either require a feature gate or not be allowed on stable.
 
 fn _test6<#[empty_attr] T>() {}
-//~^ ERROR: unknown to the compiler
+//~^ ERROR: expected an inert attribute, found an attribute macro
 
 fn _test7() {
     match 1 {
-        #[empty_attr] //~ ERROR: unknown to the compiler
+        #[empty_attr] //~ ERROR: expected an inert attribute, found an attribute macro
         0 => {}
         _ => {}
     }
diff --git a/src/test/ui/proc-macro/proc-macro-gates2.stderr b/src/test/ui/proc-macro/proc-macro-gates2.stderr
index a7f6f8b..fd271da 100644
--- a/src/test/ui/proc-macro/proc-macro-gates2.stderr
+++ b/src/test/ui/proc-macro/proc-macro-gates2.stderr
@@ -1,21 +1,14 @@
-error[E0658]: the attribute `empty_attr` is currently unknown to the compiler and may have meaning added to it in the future
+error: expected an inert attribute, found an attribute macro
   --> $DIR/proc-macro-gates2.rs:12:11
    |
 LL | fn _test6<#[empty_attr] T>() {}
    |           ^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
 
-error[E0658]: the attribute `empty_attr` is currently unknown to the compiler and may have meaning added to it in the future
+error: expected an inert attribute, found an attribute macro
   --> $DIR/proc-macro-gates2.rs:17:9
    |
 LL |         #[empty_attr]
    |         ^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs
index 0a7861a..d2282af 100644
--- a/src/test/ui/proc-macro/resolve-error.rs
+++ b/src/test/ui/proc-macro/resolve-error.rs
@@ -23,12 +23,12 @@
 //~^ ERROR cannot find
 struct Foo;
 
-// Interpreted as a feature gated custom attribute
-#[attr_proc_macra] //~ ERROR cannot find attribute macro `attr_proc_macra` in this scope
+// Interpreted as an unstable custom attribute
+#[attr_proc_macra] //~ ERROR cannot find attribute `attr_proc_macra` in this scope
 struct Bar;
 
-// Interpreted as a feature gated custom attribute
-#[FooWithLongNan] //~ ERROR cannot find attribute macro `FooWithLongNan` in this scope
+// Interpreted as an unstable custom attribute
+#[FooWithLongNan] //~ ERROR cannot find attribute `FooWithLongNan` in this scope
 struct Asdf;
 
 #[derive(Dlone)]
diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr
index 2a5f2b8..3dca5ce 100644
--- a/src/test/ui/proc-macro/resolve-error.stderr
+++ b/src/test/ui/proc-macro/resolve-error.stderr
@@ -1,22 +1,22 @@
-error: cannot find macro `bang_proc_macrp!` in this scope
+error: cannot find macro `bang_proc_macrp` in this scope
   --> $DIR/resolve-error.rs:56:5
    |
 LL |     bang_proc_macrp!();
    |     ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro`
 
-error: cannot find macro `Dlona!` in this scope
+error: cannot find macro `Dlona` in this scope
   --> $DIR/resolve-error.rs:53:5
    |
 LL |     Dlona!();
    |     ^^^^^
 
-error: cannot find macro `attr_proc_macra!` in this scope
+error: cannot find macro `attr_proc_macra` in this scope
   --> $DIR/resolve-error.rs:50:5
    |
 LL |     attr_proc_macra!();
    |     ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac`
 
-error: cannot find macro `FooWithLongNama!` in this scope
+error: cannot find macro `FooWithLongNama` in this scope
   --> $DIR/resolve-error.rs:47:5
    |
 LL |     FooWithLongNama!();
@@ -40,13 +40,13 @@
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
 
-error: cannot find attribute macro `FooWithLongNan` in this scope
+error: cannot find attribute `FooWithLongNan` in this scope
   --> $DIR/resolve-error.rs:31:3
    |
 LL | #[FooWithLongNan]
    |   ^^^^^^^^^^^^^^
 
-error: cannot find attribute macro `attr_proc_macra` in this scope
+error: cannot find attribute `attr_proc_macra` in this scope
   --> $DIR/resolve-error.rs:27:3
    |
 LL | #[attr_proc_macra]
diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr
index df5cff1..f2db17e4 100644
--- a/src/test/ui/reachable/expr_call.stderr
+++ b/src/test/ui/reachable/expr_call.stderr
@@ -10,11 +10,11 @@
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: unreachable expression
+error: unreachable call
   --> $DIR/expr_call.rs:18:5
    |
 LL |     bar(return);
-   |     ^^^^^^^^^^^
+   |     ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr
index bbfa2ef..947ea0f 100644
--- a/src/test/ui/reachable/expr_method.stderr
+++ b/src/test/ui/reachable/expr_method.stderr
@@ -10,11 +10,11 @@
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: unreachable expression
-  --> $DIR/expr_method.rs:21:5
+error: unreachable call
+  --> $DIR/expr_method.rs:21:9
    |
 LL |     Foo.bar(return);
-   |     ^^^^^^^^^^^^^^^
+   |         ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/recursion/recursive-requirements.stderr b/src/test/ui/recursion/recursive-requirements.stderr
index b304190..9846c93 100644
--- a/src/test/ui/recursion/recursive-requirements.stderr
+++ b/src/test/ui/recursion/recursive-requirements.stderr
@@ -1,20 +1,21 @@
 error[E0277]: `*const Bar` cannot be shared between threads safely
   --> $DIR/recursive-requirements.rs:16:12
    |
+LL | struct AssertSync<T: Sync>(PhantomData<T>);
+   | ------------------------------------------- required by `AssertSync`
+...
 LL |     let _: AssertSync<Foo> = unimplemented!();
    |            ^^^^^^^^^^^^^^^ `*const Bar` cannot be shared between threads safely
    |
    = help: within `Foo`, the trait `std::marker::Sync` is not implemented for `*const Bar`
    = note: required because it appears within the type `Foo`
-note: required by `AssertSync`
-  --> $DIR/recursive-requirements.rs:3:1
-   |
-LL | struct AssertSync<T: Sync>(PhantomData<T>);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `*const Foo` cannot be shared between threads safely
   --> $DIR/recursive-requirements.rs:16:12
    |
+LL | struct AssertSync<T: Sync>(PhantomData<T>);
+   | ------------------------------------------- required by `AssertSync`
+...
 LL |     let _: AssertSync<Foo> = unimplemented!();
    |            ^^^^^^^^^^^^^^^ `*const Foo` cannot be shared between threads safely
    |
@@ -22,11 +23,6 @@
    = note: required because it appears within the type `Bar`
    = note: required because it appears within the type `std::marker::PhantomData<Bar>`
    = note: required because it appears within the type `Foo`
-note: required by `AssertSync`
-  --> $DIR/recursive-requirements.rs:3:1
-   |
-LL | struct AssertSync<T: Sync>(PhantomData<T>);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs
index 45910c3..f6b3178 100644
--- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs
@@ -6,7 +6,7 @@
     let Ok(x) = res;
     //~^ ERROR refutable pattern
     x
-    //~^ ERROR use of possibly uninitialized variable: `x`
+    //~^ ERROR use of possibly-uninitialized variable: `x`
 }
 
 fn main() {
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
index eee331d..b938595 100644
--- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
@@ -4,11 +4,11 @@
 LL |     let Ok(x) = res;
    |         ^^^^^ pattern `Err(_)` not covered
 
-error[E0381]: use of possibly uninitialized variable: `x`
+error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/recursive-types-are-not-uninhabited.rs:8:5
    |
 LL |     x
-   |     ^ use of possibly uninitialized `x`
+   |     ^ use of possibly-uninitialized `x`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/refutable-pattern-errors.rs b/src/test/ui/refutable-pattern-errors.rs
index aa5fa76..d4afe17 100644
--- a/src/test/ui/refutable-pattern-errors.rs
+++ b/src/test/ui/refutable-pattern-errors.rs
@@ -1,7 +1,9 @@
+// ignore-tidy-linelength
+
 fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
 //~^ ERROR refutable pattern in function argument: `(_, _)` not covered
 
 fn main() {
     let (1, (Some(1), 2..=3)) = (1, (None, 2));
-    //~^ ERROR refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` not covered
+    //~^ ERROR refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
 }
diff --git a/src/test/ui/refutable-pattern-errors.stderr b/src/test/ui/refutable-pattern-errors.stderr
index c67ae7c..3b13e25 100644
--- a/src/test/ui/refutable-pattern-errors.stderr
+++ b/src/test/ui/refutable-pattern-errors.stderr
@@ -1,14 +1,14 @@
 error[E0005]: refutable pattern in function argument: `(_, _)` not covered
-  --> $DIR/refutable-pattern-errors.rs:1:9
+  --> $DIR/refutable-pattern-errors.rs:3:9
    |
 LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
    |         ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered
 
-error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` not covered
-  --> $DIR/refutable-pattern-errors.rs:5:9
+error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
+  --> $DIR/refutable-pattern-errors.rs:7:9
    |
 LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2));
-   |         ^^^^^^^^^^^^^^^^^^^^^ pattern `(std::i32::MIN..=0i32, _)` not covered
+   |         ^^^^^^^^^^^^^^^^^^^^^ patterns `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/reify-intrinsic.rs b/src/test/ui/reify-intrinsic.rs
new file mode 100644
index 0000000..09baa05
--- /dev/null
+++ b/src/test/ui/reify-intrinsic.rs
@@ -0,0 +1,15 @@
+// check-fail
+
+#![feature(intrinsics)]
+
+fn a() {
+    let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute;
+    //~^ ERROR cannot coerce
+}
+
+fn b() {
+    let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
+    //~^ ERROR casting
+}
+
+fn main() {}
diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr
new file mode 100644
index 0000000..4a1bd77
--- /dev/null
+++ b/src/test/ui/reify-intrinsic.stderr
@@ -0,0 +1,22 @@
+error[E0308]: cannot coerce intrinsics to function pointers
+  --> $DIR/reify-intrinsic.rs:6:64
+   |
+LL |     let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute;
+   |                                                                ^^^^^^^^^^^^^^^^^^^
+   |                                                                |
+   |                                                                cannot coerce intrinsics to function pointers
+   |                                                                help: use parentheses to call this function: `std::mem::transmute(...)`
+   |
+   = note: expected type `unsafe extern "rust-intrinsic" fn(isize) -> usize`
+              found type `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
+
+error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
+  --> $DIR/reify-intrinsic.rs:11:13
+   |
+LL |     let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0606.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.rs b/src/test/ui/reserved/reserved-attr-on-macro.rs
index fddb991..2630db0 100644
--- a/src/test/ui/reserved/reserved-attr-on-macro.rs
+++ b/src/test/ui/reserved/reserved-attr-on-macro.rs
@@ -1,5 +1,5 @@
 #[rustc_attribute_should_be_reserved]
-//~^ ERROR cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
+//~^ ERROR cannot find attribute `rustc_attribute_should_be_reserved` in this scope
 //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
 
 macro_rules! foo {
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr
index 856162b..6859605 100644
--- a/src/test/ui/reserved/reserved-attr-on-macro.stderr
+++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr
@@ -15,7 +15,7 @@
    |
    = note: import resolution is stuck, try simplifying macro imports
 
-error: cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
+error: cannot find attribute `rustc_attribute_should_be_reserved` in this scope
   --> $DIR/reserved-attr-on-macro.rs:1:3
    |
 LL | #[rustc_attribute_should_be_reserved]
diff --git a/src/test/ui/resolve/block-with-trait-parent.rs b/src/test/ui/resolve/block-with-trait-parent.rs
new file mode 100644
index 0000000..bc86f94
--- /dev/null
+++ b/src/test/ui/resolve/block-with-trait-parent.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+trait Trait {
+    fn method(&self) {
+        // Items inside a block turn it into a module internally.
+        struct S;
+        impl Trait for S {}
+
+        // OK, `Trait` is in scope here from method resolution point of view.
+        S.method();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr
index 968c1f3..63ac11d 100644
--- a/src/test/ui/resolve/issue-3907-2.stderr
+++ b/src/test/ui/resolve/issue-3907-2.stderr
@@ -4,7 +4,7 @@
 LL | fn bar(_x: Foo) {}
    | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object
    |
-   = note: method `bar` has no receiver
+   = note: associated function `bar` has no `self` parameter
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/visibility-indeterminate.rs b/src/test/ui/resolve/visibility-indeterminate.rs
index 595eaf4..0e1142d 100644
--- a/src/test/ui/resolve/visibility-indeterminate.rs
+++ b/src/test/ui/resolve/visibility-indeterminate.rs
@@ -1,5 +1,7 @@
 // edition:2018
 
-foo!(); //~ ERROR cannot find macro `foo!` in this scope
+foo!(); //~ ERROR cannot find macro `foo` in this scope
 
 pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility
+
+fn main() {}
diff --git a/src/test/ui/resolve/visibility-indeterminate.stderr b/src/test/ui/resolve/visibility-indeterminate.stderr
index a259c80..b967829 100644
--- a/src/test/ui/resolve/visibility-indeterminate.stderr
+++ b/src/test/ui/resolve/visibility-indeterminate.stderr
@@ -4,16 +4,11 @@
 LL | pub(in ::bar) struct Baz {}
    |        ^^^^^
 
-error: cannot find macro `foo!` in this scope
+error: cannot find macro `foo` in this scope
   --> $DIR/visibility-indeterminate.rs:3:1
    |
 LL | foo!();
    | ^^^
 
-error[E0601]: `main` function not found in crate `visibility_indeterminate`
-   |
-   = note: consider adding a `main` function to `$DIR/visibility-indeterminate.rs`
+error: aborting due to 2 previous errors
 
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
index e43c8541e6..1e08616 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
@@ -4,15 +4,13 @@
 
 // run-pass
 
-#![feature(bind_by_move_pattern_guards)]
-
 use std::sync::mpsc::channel;
 
 fn main() {
     let (tx, rx) = channel();
     let x = Some(rx);
-    tx.send(false);
-    tx.send(false);
+    tx.send(false).unwrap();
+    tx.send(false).unwrap();
     match x {
         Some(z) if z.recv().unwrap() => { panic!() },
         Some(z) => { assert!(!z.recv().unwrap()); },
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr
deleted file mode 100644
index fe1f699..0000000
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2015.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: compilation successful
-  --> $DIR/feature-gate.rs:36:1
-   |
-LL | / fn main() {
-LL | |     foo(107)
-LL | | }
-   | |_^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr
deleted file mode 100644
index fe1f699..0000000
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_2018.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: compilation successful
-  --> $DIR/feature-gate.rs:36:1
-   |
-LL | / fn main() {
-LL | |     foo(107)
-LL | | }
-   | |_^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr
deleted file mode 100644
index 34e8b0e..0000000
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_feature_nll.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: compilation successful
-  --> $DIR/feature-gate.rs:41:1
-   |
-LL | / fn main() {
-LL | |     foo(107)
-LL | | }
-   | |_^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr
deleted file mode 100644
index 34e8b0e..0000000
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.gate_and_znll.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: compilation successful
-  --> $DIR/feature-gate.rs:41:1
-   |
-LL | / fn main() {
-LL | |     foo(107)
-LL | | }
-   | |_^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
deleted file mode 100644
index 7a7b1c2..0000000
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0008]: cannot bind by-move into a pattern guard
-  --> $DIR/feature-gate.rs:28:16
-   |
-LL |         A { a: v } if *v == 42 => v,
-   |                ^ moves value into pattern guard
-   |
-   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0008`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs
deleted file mode 100644
index 69fce0b..0000000
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Check that pattern-guards with move-bound variables is only allowed
-// with the appropriate set of feature gates. (Note that we require
-// the code to opt into MIR-borrowck in *some* way before the feature
-// will work; we use the revision system here to enumerate a number of
-// ways that opt-in could occur.)
-
-// gate-test-bind_by_move_pattern_guards
-
-// revisions: no_gate gate_and_2015 gate_and_2018
-
-// (We're already testing NLL behavior quite explicitly, no need for compare-mode=nll.)
-// ignore-compare-mode-nll
-
-#![feature(rustc_attrs)]
-
-#![cfg_attr(gate_and_2015, feature(bind_by_move_pattern_guards))]
-#![cfg_attr(gate_and_2018, feature(bind_by_move_pattern_guards))]
-
-//[gate_and_2015] edition:2015
-//[gate_and_2018] edition:2018
-
-struct A { a: Box<i32> }
-
-fn foo(n: i32) {
-    let x = A { a: Box::new(n) };
-    let _y = match x {
-
-        A { a: v } if *v == 42 => v,
-        //[no_gate]~^ ERROR cannot bind by-move into a pattern guard
-
-        _ => Box::new(0)
-    };
-}
-
-#[rustc_error]
-fn main() {
-    foo(107)
-}
-//[gate_and_2015]~^^^ ERROR compilation successful
-//[gate_and_2018]~^^^^ ERROR compilation successful
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs
new file mode 100644
index 0000000..3161d6f
--- /dev/null
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs
@@ -0,0 +1,11 @@
+// This test used to emit E0008 but now passed since `bind_by_move_pattern_guards`
+// have been stabilized.
+
+// check-pass
+
+fn main() {
+    match Some("hi".to_string()) {
+        Some(s) if s.len() == 0 => {},
+        _ => {},
+    }
+}
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
index eccb4e41..b716fc8 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
@@ -1,5 +1,3 @@
-#![feature(bind_by_move_pattern_guards)]
-
 // run-pass
 
 struct A { a: Box<i32> }
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
index 602a8e1..d1f685f 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
@@ -1,5 +1,3 @@
-#![feature(bind_by_move_pattern_guards)]
-
 enum VecWrapper { A(Vec<i32>) }
 
 fn foo(x: VecWrapper) -> usize {
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
index c9e8fc8..7becd01 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `v` in pattern guard
-  --> $DIR/rfc-reject-double-move-across-arms.rs:7:36
+  --> $DIR/rfc-reject-double-move-across-arms.rs:5:36
    |
 LL |         VecWrapper::A(v) if { drop(v); false } => 1,
    |                                    ^ move occurs because `v` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
index 77252a1..571f51c 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
@@ -1,5 +1,3 @@
-#![feature(bind_by_move_pattern_guards)]
-
 struct A { a: Box<i32> }
 
 fn foo(n: i32) {
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
index a345022..b93e721 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `v` in pattern guard
-  --> $DIR/rfc-reject-double-move-in-first-arm.rs:8:30
+  --> $DIR/rfc-reject-double-move-in-first-arm.rs:6:30
    |
 LL |         A { a: v } if { drop(v); true } => v,
    |                              ^ move occurs because `v` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs
index 470a5ea..fe7df44 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/variants_same_crate.rs
@@ -10,11 +10,11 @@
 
 fn main() {
     let variant_tuple = NonExhaustiveVariants::Tuple(340);
-    let variant_struct = NonExhaustiveVariants::Struct { field: 340 };
+    let _variant_struct = NonExhaustiveVariants::Struct { field: 340 };
 
     match variant_tuple {
         NonExhaustiveVariants::Unit => "",
-        NonExhaustiveVariants::Tuple(fe_tpl) => "",
-        NonExhaustiveVariants::Struct { field } => ""
+        NonExhaustiveVariants::Tuple(_fe_tpl) => "",
+        NonExhaustiveVariants::Struct { field: _ } => ""
     };
 }
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
index e885263..04d924a 100644
--- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
@@ -1,7 +1,5 @@
 // run-pass
-// ignore-cloudabi no processes
-// ignore-emscripten no processes
-// ignore-sgx no processes
+// check-run-results
 
 // Tests ensuring that `dbg!(expr)` has the expected run-time behavior.
 // as well as some compile time properties we expect.
@@ -18,7 +16,7 @@
 #[derive(Debug, PartialEq)]
 struct NoCopy(usize);
 
-fn test() {
+fn main() {
     let a: Unit = dbg!(Unit);
     let _: Unit = dbg!(a);
     // We can move `a` because it's Copy.
@@ -67,81 +65,3 @@
     assert_eq!((1u8, 2u32, "Yeah"), dbg!(1u8, 2u32,
                                          "Yeah",));
 }
-
-fn validate_stderr(stderr: Vec<String>) {
-    assert_eq!(stderr, &[
-        ":22] Unit = Unit",
-
-        ":23] a = Unit",
-
-        ":29] Point{x: 42, y: 24,} = Point {",
-        "    x: 42,",
-        "    y: 24,",
-        "}",
-
-        ":30] b = Point {",
-        "    x: 42,",
-        "    y: 24,",
-        "}",
-
-        ":38]",
-
-        ":42] &a = NoCopy(",
-        "    1337,",
-        ")",
-
-        ":42] dbg!(& a) = NoCopy(",
-        "    1337,",
-        ")",
-        ":47] f(&42) = 42",
-
-        "before",
-        ":52] { foo += 1; eprintln!(\"before\"); 7331 } = 7331",
-
-        ":60] (\"Yeah\",) = (",
-        "    \"Yeah\",",
-        ")",
-
-        ":63] 1 = 1",
-        ":63] 2 = 2",
-
-        ":67] 1u8 = 1",
-        ":67] 2u32 = 2",
-        ":67] \"Yeah\" = \"Yeah\"",
-    ]);
-}
-
-fn main() {
-    // The following is a hack to deal with compiletest's inability
-    // to check the output (to stdout) of run-pass tests.
-    use std::env;
-    use std::process::Command;
-
-    let mut args = env::args();
-    let prog = args.next().unwrap();
-    let child = args.next();
-    if let Some("child") = child.as_ref().map(|s| &**s) {
-        // Only run the test if we've been spawned as 'child'
-        test()
-    } else {
-        // This essentially spawns as 'child' to run the tests
-        // and then it collects output of stderr and checks the output
-        // against what we expect.
-        let out = Command::new(&prog).arg("child").output().unwrap();
-        assert!(out.status.success());
-        assert!(out.stdout.is_empty());
-
-        let stderr = String::from_utf8(out.stderr).unwrap();
-        let stderr = stderr.lines().map(|mut s| {
-            if s.starts_with("[") {
-                // Strip `[` and file path:
-                s = s.trim_start_matches("[");
-                assert!(s.starts_with(file!()));
-                s = s.trim_start_matches(file!());
-            }
-            s.to_owned()
-        }).collect();
-
-        validate_stderr(stderr);
-    }
-}
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
new file mode 100644
index 0000000..707b38c
--- /dev/null
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
@@ -0,0 +1,28 @@
+[$DIR/dbg-macro-expected-behavior.rs:20] Unit = Unit
+[$DIR/dbg-macro-expected-behavior.rs:21] a = Unit
+[$DIR/dbg-macro-expected-behavior.rs:27] Point{x: 42, y: 24,} = Point {
+    x: 42,
+    y: 24,
+}
+[$DIR/dbg-macro-expected-behavior.rs:28] b = Point {
+    x: 42,
+    y: 24,
+}
+[$DIR/dbg-macro-expected-behavior.rs:36]
+[$DIR/dbg-macro-expected-behavior.rs:40] &a = NoCopy(
+    1337,
+)
+[$DIR/dbg-macro-expected-behavior.rs:40] dbg!(& a) = NoCopy(
+    1337,
+)
+[$DIR/dbg-macro-expected-behavior.rs:45] f(&42) = 42
+before
+[$DIR/dbg-macro-expected-behavior.rs:50] { foo += 1; eprintln!("before"); 7331 } = 7331
+[$DIR/dbg-macro-expected-behavior.rs:58] ("Yeah",) = (
+    "Yeah",
+)
+[$DIR/dbg-macro-expected-behavior.rs:61] 1 = 1
+[$DIR/dbg-macro-expected-behavior.rs:61] 2 = 2
+[$DIR/dbg-macro-expected-behavior.rs:65] 1u8 = 1
+[$DIR/dbg-macro-expected-behavior.rs:65] 2u32 = 2
+[$DIR/dbg-macro-expected-behavior.rs:65] "Yeah" = "Yeah"
diff --git a/src/test/ui/rfc-2497-if-let-chains/protect-precedences.rs b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.rs
index 1de4e5b..b95105b 100644
--- a/src/test/ui/rfc-2497-if-let-chains/protect-precedences.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.rs
@@ -2,8 +2,6 @@
 
 #![allow(irrefutable_let_patterns)]
 
-use std::ops::Range;
-
 fn main() {
     let x: bool;
     // This should associate as: `(x = (true && false));`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr
new file mode 100644
index 0000000..be7ef65
--- /dev/null
+++ b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr
@@ -0,0 +1,8 @@
+warning: unreachable block in `if` expression
+  --> $DIR/protect-precedences.rs:13:41
+   |
+LL |         if let _ = return true && false {};
+   |                                         ^^
+   |
+   = note: `#[warn(unreachable_code)]` on by default
+
diff --git a/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs b/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs
new file mode 100644
index 0000000..b62cf31
--- /dev/null
+++ b/src/test/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs
@@ -0,0 +1,11 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn id(_: TokenStream, input: TokenStream) -> TokenStream { input }
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
index b957c67..a8fe5d6 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
@@ -5,7 +5,7 @@
         /// Foo
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR the attribute `test` is currently unknown to the compiler and may have
+        //~^ ERROR expected an inert attribute, found an attribute macro
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -21,7 +21,7 @@
     /// Foo
     //~^ ERROR documentation comments cannot be applied to function
     #[test] a: u32,
-    //~^ ERROR the attribute `test` is currently unknown to the compiler and may have
+    //~^ ERROR expected an inert attribute, found an attribute macro
     /// Bar
     //~^ ERROR documentation comments cannot be applied to function
     #[must_use]
@@ -36,7 +36,7 @@
     /// Foo
     //~^ ERROR documentation comments cannot be applied to function
     #[test] a: u32,
-    //~^ ERROR the attribute `test` is currently unknown to the compiler and may have
+    //~^ ERROR expected an inert attribute, found an attribute macro
     /// Bar
     //~^ ERROR documentation comments cannot be applied to function
     #[must_use]
@@ -56,7 +56,7 @@
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR the attribute `test` is currently unknown to the compiler and may have
+        //~^ ERROR expected an inert attribute, found an attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -77,7 +77,7 @@
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR the attribute `test` is currently unknown to the compiler and may have
+        //~^ ERROR expected an inert attribute, found an attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -96,7 +96,7 @@
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR the attribute `test` is currently unknown to the compiler and may have
+        //~^ ERROR expected an inert attribute, found an attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -115,7 +115,7 @@
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: i32,
-        //~^ ERROR the attribute `test` is currently unknown to the compiler and may have
+        //~^ ERROR expected an inert attribute, found an attribute macro
         /// Baz
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
@@ -132,7 +132,7 @@
         /// Foo
         //~^ ERROR documentation comments cannot be applied to function
         #[test] a: u32,
-        //~^ ERROR the attribute `test` is currently unknown to the compiler and may have
+        //~^ ERROR expected an inert attribute, found an attribute macro
         /// Bar
         //~^ ERROR documentation comments cannot be applied to function
         #[must_use]
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
index a57572a..8ab3fc3 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
@@ -1,3 +1,51 @@
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:7:9
+   |
+LL |         #[test] a: i32,
+   |         ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:23:5
+   |
+LL |     #[test] a: u32,
+   |     ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:38:5
+   |
+LL |     #[test] a: u32,
+   |     ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:58:9
+   |
+LL |         #[test] a: i32,
+   |         ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:79:9
+   |
+LL |         #[test] a: i32,
+   |         ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:98:9
+   |
+LL |         #[test] a: i32,
+   |         ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:117:9
+   |
+LL |         #[test] a: i32,
+   |         ^^^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/param-attrs-builtin-attrs.rs:134:9
+   |
+LL |         #[test] a: u32,
+   |         ^^^^^^^
+
 error: documentation comments cannot be applied to function parameters
   --> $DIR/param-attrs-builtin-attrs.rs:5:9
    |
@@ -262,78 +310,5 @@
 LL |         #[no_mangle] b: i32
    |         ^^^^^^^^^^^^
 
-error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/param-attrs-builtin-attrs.rs:7:9
-   |
-LL |         #[test] a: i32,
-   |         ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/param-attrs-builtin-attrs.rs:23:5
-   |
-LL |     #[test] a: u32,
-   |     ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/param-attrs-builtin-attrs.rs:38:5
-   |
-LL |     #[test] a: u32,
-   |     ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/param-attrs-builtin-attrs.rs:58:9
-   |
-LL |         #[test] a: i32,
-   |         ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/param-attrs-builtin-attrs.rs:79:9
-   |
-LL |         #[test] a: i32,
-   |         ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/param-attrs-builtin-attrs.rs:98:9
-   |
-LL |         #[test] a: i32,
-   |         ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/param-attrs-builtin-attrs.rs:117:9
-   |
-LL |         #[test] a: i32,
-   |         ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
-error[E0658]: the attribute `test` is currently unknown to the compiler and may have meaning added to it in the future
-  --> $DIR/param-attrs-builtin-attrs.rs:134:9
-   |
-LL |         #[test] a: u32,
-   |         ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
-   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
-
 error: aborting due to 52 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs
new file mode 100644
index 0000000..7f00308
--- /dev/null
+++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs
@@ -0,0 +1,60 @@
+// aux-build:ident-mac.rs
+
+#![feature(param_attrs)]
+#![feature(c_variadic)]
+
+extern crate ident_mac;
+use ident_mac::id;
+
+struct W(u8);
+
+extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); }
+//~^ ERROR expected an inert attribute, found an attribute macro
+//~| ERROR expected an inert attribute, found an attribute macro
+
+unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {}
+//~^ ERROR expected an inert attribute, found an attribute macro
+
+type Alias = extern "C" fn(#[id] u8, #[id] ...);
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+
+fn free(#[id] arg1: u8) {
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    let lam = |#[id] W(x), #[id] y| ();
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+}
+
+impl W {
+    fn inherent1(#[id] self, #[id] arg1: u8) {}
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+    fn inherent2(#[id] &self, #[id] arg1: u8) {}
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+    fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {}
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+    fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+}
+
+trait A {
+    fn trait1(#[id] self, #[id] arg1: u8);
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+    fn trait2(#[id] &self, #[id] arg1: u8);
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+    fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+    fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
+    //~^ ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+    //~| ERROR expected an inert attribute, found an attribute macro
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr
new file mode 100644
index 0000000..3b72e8a
--- /dev/null
+++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr
@@ -0,0 +1,152 @@
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:11:21
+   |
+LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); }
+   |                     ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:11:38
+   |
+LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); }
+   |                                      ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:15:38
+   |
+LL | unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {}
+   |                                      ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:18:28
+   |
+LL | type Alias = extern "C" fn(#[id] u8, #[id] ...);
+   |                            ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:18:38
+   |
+LL | type Alias = extern "C" fn(#[id] u8, #[id] ...);
+   |                                      ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:22:9
+   |
+LL | fn free(#[id] arg1: u8) {
+   |         ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:24:16
+   |
+LL |     let lam = |#[id] W(x), #[id] y| ();
+   |                ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:24:28
+   |
+LL |     let lam = |#[id] W(x), #[id] y| ();
+   |                            ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:30:18
+   |
+LL |     fn inherent1(#[id] self, #[id] arg1: u8) {}
+   |                  ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:30:30
+   |
+LL |     fn inherent1(#[id] self, #[id] arg1: u8) {}
+   |                              ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:33:18
+   |
+LL |     fn inherent2(#[id] &self, #[id] arg1: u8) {}
+   |                  ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:33:31
+   |
+LL |     fn inherent2(#[id] &self, #[id] arg1: u8) {}
+   |                               ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:36:22
+   |
+LL |     fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {}
+   |                      ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:36:42
+   |
+LL |     fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {}
+   |                                          ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:39:22
+   |
+LL |     fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
+   |                      ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:39:45
+   |
+LL |     fn inherent4<'a>(#[id] self: Box<Self>, #[id] arg1: u8) {}
+   |                                             ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:45:15
+   |
+LL |     fn trait1(#[id] self, #[id] arg1: u8);
+   |               ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:45:27
+   |
+LL |     fn trait1(#[id] self, #[id] arg1: u8);
+   |                           ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:48:15
+   |
+LL |     fn trait2(#[id] &self, #[id] arg1: u8);
+   |               ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:48:28
+   |
+LL |     fn trait2(#[id] &self, #[id] arg1: u8);
+   |                            ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:51:19
+   |
+LL |     fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
+   |                   ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:51:39
+   |
+LL |     fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8);
+   |                                       ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:54:19
+   |
+LL |     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
+   |                   ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:54:42
+   |
+LL |     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
+   |                                          ^^^^^
+
+error: expected an inert attribute, found an attribute macro
+  --> $DIR/proc-macro-cannot-be-used.rs:54:58
+   |
+LL |     fn trait4<'a>(#[id] self: Box<Self>, #[id] arg1: u8, #[id] Vec<u8>);
+   |                                                          ^^^^^
+
+error: aborting due to 25 previous errors
+
diff --git a/src/test/ui/rfc1445/fn-ptr-is-structurally-matchable.rs b/src/test/ui/rfc1445/fn-ptr-is-structurally-matchable.rs
new file mode 100644
index 0000000..5b378fb
--- /dev/null
+++ b/src/test/ui/rfc1445/fn-ptr-is-structurally-matchable.rs
@@ -0,0 +1,135 @@
+// run-pass
+
+// This file checks that fn ptrs are considered structurally matchable.
+// See also rust-lang/rust#63479.
+
+fn main() {
+    let mut count = 0;
+
+    // A type which is not structurally matchable:
+    struct NotSM;
+
+    // And one that is:
+    #[derive(PartialEq, Eq)]
+    struct SM;
+
+    fn trivial() {}
+
+    fn sm_to(_: SM) {}
+    fn not_sm_to(_: NotSM) {}
+    fn to_sm() -> SM { SM }
+    fn to_not_sm() -> NotSM { NotSM }
+
+    // To recreate the scenario of interest in #63479, we need to add
+    // a ref-level-of-indirection so that we descend into the type.
+
+    fn r_sm_to(_: &SM) {}
+    fn r_not_sm_to(_: &NotSM) {}
+    fn r_to_r_sm(_: &()) -> &SM { &SM }
+    fn r_to_r_not_sm(_: &()) -> &NotSM { &NotSM }
+
+    #[derive(PartialEq, Eq)]
+    struct Wrap<T>(T);
+
+    // In the code below, we put the match input into a local so that
+    // we can assign it an explicit type that is an fn ptr instead of
+    // a singleton type of the fn itself that the type inference would
+    // otherwise assign.
+
+    // Check that fn() is #[structural_match]
+    const CFN1: Wrap<fn()> = Wrap(trivial);
+    let input: Wrap<fn()> = Wrap(trivial);
+    match Wrap(input) {
+        Wrap(CFN1) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn(T) is #[structural_match] when T is too.
+    const CFN2: Wrap<fn(SM)> = Wrap(sm_to);
+    let input: Wrap<fn(SM)> = Wrap(sm_to);
+    match Wrap(input) {
+        Wrap(CFN2) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn() -> T is #[structural_match] when T is too.
+    const CFN3: Wrap<fn() -> SM> = Wrap(to_sm);
+    let input: Wrap<fn() -> SM> = Wrap(to_sm);
+    match Wrap(input) {
+        Wrap(CFN3) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn(T) is #[structural_match] even if T is not.
+    const CFN4: Wrap<fn(NotSM)> = Wrap(not_sm_to);
+    let input: Wrap<fn(NotSM)> = Wrap(not_sm_to);
+    match Wrap(input) {
+        Wrap(CFN4) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn() -> T is #[structural_match] even if T is not.
+    const CFN5: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
+    let input: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
+    match Wrap(input) {
+        Wrap(CFN5) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn(&T) is #[structural_match] when T is too.
+    const CFN6: Wrap<fn(&SM)> = Wrap(r_sm_to);
+    let input: Wrap<fn(&SM)> = Wrap(r_sm_to);
+    match Wrap(input) {
+        Wrap(CFN6) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn() -> &T is #[structural_match] when T is too.
+    const CFN7: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
+    let input: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
+    match Wrap(input) {
+        Wrap(CFN7) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn(T) is #[structural_match] even if T is not.
+    const CFN8: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
+    let input: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
+    match Wrap(input) {
+        Wrap(CFN8) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn() -> T is #[structural_match] even if T is not.
+    const CFN9: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
+    let input: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
+    match Wrap(input) {
+        Wrap(CFN9) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that a type which has fn ptrs is `#[structural_match]`.
+    #[derive(PartialEq, Eq)]
+    struct Foo {
+        alpha: fn(NotSM),
+        beta: fn() -> NotSM,
+        gamma: fn(SM),
+        delta: fn() -> SM,
+    }
+
+    const CFOO: Foo = Foo {
+        alpha: not_sm_to,
+        beta: to_not_sm,
+        gamma: sm_to,
+        delta: to_sm,
+    };
+
+    let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm };
+    match input {
+        CFOO => count += 1,
+        Foo { .. } => {}
+    };
+
+    // Final count must be 10 now if all
+    assert_eq!(count, 10);
+}
diff --git a/src/test/ui/rfc1445/issue-63479-match-fnptr.rs b/src/test/ui/rfc1445/issue-63479-match-fnptr.rs
new file mode 100644
index 0000000..b3c91ce
--- /dev/null
+++ b/src/test/ui/rfc1445/issue-63479-match-fnptr.rs
@@ -0,0 +1,36 @@
+// run-pass
+
+// The actual regression test from #63479. (Including this because my
+// first draft at fn-ptr-is-structurally-matchable.rs failed to actually
+// cover the case this hit; I've since expanded it accordingly, but the
+// experience left me wary of leaving this regression test out.)
+
+#[derive(Eq)]
+struct A {
+  a: i64
+}
+
+impl PartialEq for A {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.a.eq(&other.a)
+    }
+}
+
+type Fn = fn(&[A]);
+
+fn my_fn(_args: &[A]) {
+  println!("hello world");
+}
+
+const TEST: Fn = my_fn;
+
+struct B(Fn);
+
+fn main() {
+  let s = B(my_fn);
+  match s {
+    B(TEST) => println!("matched"),
+    _ => panic!("didn't match")
+  };
+}
diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr
index a811812..19f758f 100644
--- a/src/test/ui/rust-2018/trait-import-suggestions.stderr
+++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr
@@ -2,7 +2,7 @@
   --> $DIR/trait-import-suggestions.rs:22:11
    |
 LL |         x.foobar();
-   |           ^^^^^^
+   |           ^^^^^^ method not found in `u32`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
@@ -12,7 +12,7 @@
   --> $DIR/trait-import-suggestions.rs:28:7
    |
 LL |     x.bar();
-   |       ^^^
+   |       ^^^ method not found in `u32`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope, perhaps add a `use` for it:
@@ -24,7 +24,7 @@
   --> $DIR/trait-import-suggestions.rs:29:7
    |
 LL |     x.baz();
-   |       ^^^
+   |       ^^^ method not found in `u32`
 
 error[E0599]: no function or associated item named `from_str` found for type `u32` in the current scope
   --> $DIR/trait-import-suggestions.rs:30:18
diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.rs b/src/test/ui/rust-2018/uniform-paths/deadlock.rs
index 3228d79..83ed70a 100644
--- a/src/test/ui/rust-2018/uniform-paths/deadlock.rs
+++ b/src/test/ui/rust-2018/uniform-paths/deadlock.rs
@@ -1,7 +1,7 @@
 // edition:2018
 // compile-flags:--extern foo --extern bar
 
-use foo::bar; //~ ERROR unresolved import
+use foo::bar; //~ ERROR can't find crate for `foo`
 use bar::foo;
 
 fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.stderr b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr
index b4ac15c..9336e90 100644
--- a/src/test/ui/rust-2018/uniform-paths/deadlock.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr
@@ -1,9 +1,9 @@
-error[E0432]: unresolved import
+error[E0463]: can't find crate for `foo`
   --> $DIR/deadlock.rs:4:5
    |
 LL | use foo::bar;
-   |     ^^^^^^^^
+   |     ^^^ can't find crate
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0432`.
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/save-analysis/issue-63663.rs b/src/test/ui/save-analysis/issue-63663.rs
new file mode 100644
index 0000000..92e8588
--- /dev/null
+++ b/src/test/ui/save-analysis/issue-63663.rs
@@ -0,0 +1,28 @@
+// check-pass
+// compile-flags: -Zsave-analysis
+
+pub trait Trait {
+    type Assoc;
+}
+
+pub struct A;
+
+trait Generic<T> {}
+impl<T> Generic<T> for () {}
+
+// Don't ICE when resolving type paths in return type `impl Trait`
+fn assoc_in_opaque_type_bounds<U: Trait>() -> impl Generic<U::Assoc> {}
+
+// Check that this doesn't ICE when processing associated const in formal
+// argument and return type of functions defined inside function/method scope.
+pub fn func() {
+    fn _inner1<U: Trait>(_: U::Assoc) {}
+    fn _inner2<U: Trait>() -> U::Assoc { unimplemented!() }
+
+    impl A {
+        fn _inner1<U: Trait>(self, _: U::Assoc) {}
+        fn _inner2<U: Trait>(self) -> U::Assoc { unimplemented!() }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr
index e45bc26..e6eba37 100644
--- a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr
+++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr
@@ -1,18 +1,21 @@
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/arbitrary-self-types-not-object-safe.rs:31:32
    |
+LL |     fn foo(self: &Rc<Self>) -> usize;
+   |        --- method `foo`'s `self` parameter cannot be dispatched on
+...
 LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
    |                                ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
-   |
-   = note: method `foo`'s receiver cannot be dispatched on
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/arbitrary-self-types-not-object-safe.rs:31:13
    |
+LL |     fn foo(self: &Rc<Self>) -> usize;
+   |        --- method `foo`'s `self` parameter cannot be dispatched on
+...
 LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
    |             ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
    |
-   = note: method `foo`'s receiver cannot be dispatched on
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.rs b/src/test/ui/self/point-at-arbitrary-self-type-method.rs
new file mode 100644
index 0000000..0f7deea
--- /dev/null
+++ b/src/test/ui/self/point-at-arbitrary-self-type-method.rs
@@ -0,0 +1,9 @@
+struct A;
+
+impl A {
+    fn foo(self: Box<Self>) {}
+}
+
+fn main() {
+    A.foo(); //~ ERROR E0599
+}
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
new file mode 100644
index 0000000..dec5809
--- /dev/null
+++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `foo` found for type `A` in the current scope
+  --> $DIR/point-at-arbitrary-self-type-method.rs:8:7
+   |
+LL | struct A;
+   | --------- method `foo` not found for this
+...
+LL |     fn foo(self: Box<Self>) {}
+   |        --- the method is available for `std::boxed::Box<A>` here
+...
+LL |     A.foo();
+   |       ^^^ method not found in `A`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs
new file mode 100644
index 0000000..53d9927
--- /dev/null
+++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.rs
@@ -0,0 +1,10 @@
+trait B { fn foo(self: Box<Self>); }
+struct A;
+
+impl B for A {
+    fn foo(self: Box<Self>) {}
+}
+
+fn main() {
+    A.foo() //~ ERROR E0599
+}
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
new file mode 100644
index 0000000..e93c4da
--- /dev/null
+++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
@@ -0,0 +1,18 @@
+error[E0599]: no method named `foo` found for type `A` in the current scope
+  --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7
+   |
+LL | trait B { fn foo(self: Box<Self>); }
+   |              --- the method is available for `std::boxed::Box<A>` here
+LL | struct A;
+   | --------- method `foo` not found for this
+...
+LL |     A.foo()
+   |       ^^^ method not found in `A`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `foo`, perhaps you need to implement it:
+           candidate #1: `B`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs
index 844f13c..dfb7d65 100644
--- a/src/test/ui/self/self_type_keyword.rs
+++ b/src/test/ui/self/self_type_keyword.rs
@@ -19,7 +19,7 @@
         ref mut Self => (),
         //~^ ERROR expected identifier, found keyword `Self`
         Self!() => (),
-        //~^ ERROR cannot find macro `Self!` in this scope
+        //~^ ERROR cannot find macro `Self` in this scope
         Foo { Self } => (),
         //~^ ERROR expected identifier, found keyword `Self`
     }
diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr
index bb63119..11b3b01 100644
--- a/src/test/ui/self/self_type_keyword.stderr
+++ b/src/test/ui/self/self_type_keyword.stderr
@@ -54,7 +54,7 @@
 LL | struct Bar<'Self>;
    |            ^^^^^
 
-error: cannot find macro `Self!` in this scope
+error: cannot find macro `Self` in this scope
   --> $DIR/self_type_keyword.rs:21:9
    |
 LL |         Self!() => (),
diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr
index e05da17..190159e 100644
--- a/src/test/ui/shadowed/shadowed-trait-methods.stderr
+++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr
@@ -2,7 +2,7 @@
   --> $DIR/shadowed-trait-methods.rs:13:8
    |
 LL |     ().f()
-   |        ^
+   |        ^ method not found in `()`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope, perhaps add a `use` for it:
diff --git a/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr b/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr
index 71197ef..1c51653 100644
--- a/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr
+++ b/src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr
@@ -1,8 +1,8 @@
-error[E0416]: identifier `a` is bound more than once in the same pattern
+error[E0415]: identifier `a` is bound more than once in this parameter list
   --> $DIR/shadowing-in-the-same-pattern.rs:3:10
    |
 LL | fn f((a, a): (isize, isize)) {}
-   |          ^ used in a pattern more than once
+   |          ^ used as parameter more than once
 
 error[E0416]: identifier `a` is bound more than once in the same pattern
   --> $DIR/shadowing-in-the-same-pattern.rs:6:13
@@ -12,4 +12,5 @@
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0416`.
+Some errors have detailed explanations: E0415, E0416.
+For more information about an error, try `rustc --explain E0415`.
diff --git a/src/test/ui/span/issue-27522.rs b/src/test/ui/span/issue-27522.rs
index 5c9893f..7a0cfb6 100644
--- a/src/test/ui/span/issue-27522.rs
+++ b/src/test/ui/span/issue-27522.rs
@@ -3,7 +3,7 @@
 struct SomeType {}
 
 trait Foo {
-    fn handler(self: &SomeType); //~ ERROR invalid method receiver type
+    fn handler(self: &SomeType); //~ ERROR invalid `self` parameter type
 }
 
 fn main() {}
diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr
index 88dfee1..8a254a9 100644
--- a/src/test/ui/span/issue-27522.stderr
+++ b/src/test/ui/span/issue-27522.stderr
@@ -1,11 +1,12 @@
-error[E0307]: invalid method receiver type: &SomeType
+error[E0307]: invalid `self` parameter type: &SomeType
   --> $DIR/issue-27522.rs:6:22
    |
 LL |     fn handler(self: &SomeType);
    |                      ^^^^^^^^^
    |
-   = note: type must be `Self` or a type that dereferences to it
+   = note: type of `self` must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0307`.
diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr
index 24dfdf8..1d3e33e 100644
--- a/src/test/ui/span/issue-29595.stderr
+++ b/src/test/ui/span/issue-29595.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `u8: Tr` is not satisfied
   --> $DIR/issue-29595.rs:6:17
    |
+LL |     const C: Self;
+   |     -------------- required by `Tr::C`
+...
 LL |     let a: u8 = Tr::C;
    |                 ^^^^^ the trait `Tr` is not implemented for `u8`
-   |
-note: required by `Tr::C`
-  --> $DIR/issue-29595.rs:2:5
-   |
-LL |     const C: Self;
-   |     ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
index c14fc04..bbfe4c3 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -5,7 +5,7 @@
    | ---------------- method `foo_one` not found for this
 ...
 LL |     println!("{}", MyStruct.foo_one());
-   |                             ^^^^^^^
+   |                             ^^^^^^^ method not found in `MyStruct`
    |
    = note: the method `foo_one` exists but the following trait bounds were not satisfied:
            `MyStruct : Foo`
diff --git a/src/test/ui/std-backtrace.rs b/src/test/ui/std-backtrace.rs
new file mode 100644
index 0000000..d84c493d
--- /dev/null
+++ b/src/test/ui/std-backtrace.rs
@@ -0,0 +1,75 @@
+// run-pass
+// ignore-android FIXME #17520
+// ignore-cloudabi spawning processes is not supported
+// ignore-emscripten spawning processes is not supported
+// ignore-openbsd no support for libbacktrace without filename
+// ignore-sgx no processes
+// ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
+// compile-flags:-g
+
+#![feature(backtrace)]
+
+use std::env;
+use std::process::Command;
+use std::str;
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() >= 2 && args[1] == "force" {
+        println!("{}", std::backtrace::Backtrace::force_capture());
+    } else if args.len() >= 2 {
+        println!("{}", std::backtrace::Backtrace::capture());
+    } else {
+        runtest(&args[0]);
+        println!("test ok");
+    }
+}
+
+fn runtest(me: &str) {
+    env::remove_var("RUST_BACKTRACE");
+    env::remove_var("RUST_LIB_BACKTRACE");
+
+    let p = Command::new(me).arg("a").env("RUST_BACKTRACE", "1").output().unwrap();
+    assert!(p.status.success());
+    assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n"));
+    assert!(String::from_utf8_lossy(&p.stdout).contains("backtrace::main"));
+
+    let p = Command::new(me).arg("a").env("RUST_BACKTRACE", "0").output().unwrap();
+    assert!(p.status.success());
+    assert!(String::from_utf8_lossy(&p.stdout).contains("disabled backtrace\n"));
+
+    let p = Command::new(me).arg("a").output().unwrap();
+    assert!(p.status.success());
+    assert!(String::from_utf8_lossy(&p.stdout).contains("disabled backtrace\n"));
+
+    let p = Command::new(me)
+        .arg("a")
+        .env("RUST_LIB_BACKTRACE", "1")
+        .env("RUST_BACKTRACE", "1")
+        .output()
+        .unwrap();
+    assert!(p.status.success());
+    assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n"));
+
+    let p = Command::new(me)
+        .arg("a")
+        .env("RUST_LIB_BACKTRACE", "0")
+        .env("RUST_BACKTRACE", "1")
+        .output()
+        .unwrap();
+    assert!(p.status.success());
+    assert!(String::from_utf8_lossy(&p.stdout).contains("disabled backtrace\n"));
+
+    let p = Command::new(me)
+        .arg("force")
+        .env("RUST_LIB_BACKTRACE", "0")
+        .env("RUST_BACKTRACE", "0")
+        .output()
+        .unwrap();
+    assert!(p.status.success());
+    assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n"));
+
+    let p = Command::new(me).arg("force").output().unwrap();
+    assert!(p.status.success());
+    assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n"));
+}
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr
index beb2272..08baa47 100644
--- a/src/test/ui/str/str-mut-idx.stderr
+++ b/src/test/ui/str/str-mut-idx.stderr
@@ -1,16 +1,14 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/str-mut-idx.rs:4:15
    |
+LL | fn bot<T>() -> T { loop {} }
+   | ---------------- required by `bot`
+...
 LL |     s[1..2] = bot();
    |               ^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `str`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-note: required by `bot`
-  --> $DIR/str-mut-idx.rs:1:1
-   |
-LL | fn bot<T>() -> T { loop {} }
-   | ^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/str-mut-idx.rs:4:5
diff --git a/src/test/ui/structs/struct-path-alias-bounds.stderr b/src/test/ui/structs/struct-path-alias-bounds.stderr
index 70eb261..1c2c205 100644
--- a/src/test/ui/structs/struct-path-alias-bounds.stderr
+++ b/src/test/ui/structs/struct-path-alias-bounds.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `NoClone: std::clone::Clone` is not satisfied
   --> $DIR/struct-path-alias-bounds.rs:9:13
    |
+LL | struct S<T: Clone> { a: T }
+   | ------------------ required by `S`
+...
 LL |     let s = A { a: NoClone };
    |             ^ the trait `std::clone::Clone` is not implemented for `NoClone`
-   |
-note: required by `S`
-  --> $DIR/struct-path-alias-bounds.rs:3:1
-   |
-LL | struct S<T: Clone> { a: T }
-   | ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/substs-ppaux.normal.stderr b/src/test/ui/substs-ppaux.normal.stderr
index b3b879e..4a8c99c 100644
--- a/src/test/ui/substs-ppaux.normal.stderr
+++ b/src/test/ui/substs-ppaux.normal.stderr
@@ -61,17 +61,15 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/substs-ppaux.rs:49:5
    |
+LL |     fn bar<'a, T>() where T: 'a {}
+   |     --------------------------- required by `Foo::bar`
+...
 LL |     <str as Foo<u8>>::bar;
    |     ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `str`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: required because of the requirements on the impl of `Foo<'_, '_, u8>` for `str`
-note: required by `Foo::bar`
-  --> $DIR/substs-ppaux.rs:7:5
-   |
-LL |     fn bar<'a, T>() where T: 'a {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/substs-ppaux.verbose.stderr
index 363018d..3314eb6 100644
--- a/src/test/ui/substs-ppaux.verbose.stderr
+++ b/src/test/ui/substs-ppaux.verbose.stderr
@@ -61,17 +61,15 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/substs-ppaux.rs:49:5
    |
+LL |     fn bar<'a, T>() where T: 'a {}
+   |     --------------------------- required by `Foo::bar`
+...
 LL |     <str as Foo<u8>>::bar;
    |     ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `str`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: required because of the requirements on the impl of `Foo<'_#0r, '_#1r, u8>` for `str`
-note: required by `Foo::bar`
-  --> $DIR/substs-ppaux.rs:7:5
-   |
-LL |     fn bar<'a, T>() where T: 'a {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
new file mode 100644
index 0000000..a2d2ba1
--- /dev/null
+++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
@@ -0,0 +1,10 @@
+// edition:2018
+use std::future::Future;
+
+async fn foo() {}
+
+fn bar(f: impl Future<Output=()>) {}
+
+fn main() {
+    bar(foo); //~ERROR E0277
+}
diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
new file mode 100644
index 0000000..3141b1b
--- /dev/null
+++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `fn() -> impl std::future::Future {foo}: std::future::Future` is not satisfied
+  --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:9:5
+   |
+LL | fn bar(f: impl Future<Output=()>) {}
+   | --------------------------------- required by `bar`
+...
+LL |     bar(foo);
+   |     ^^^ the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}`
+   |
+   = help: use parentheses to call the function: `foo()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/attribute-typos.rs b/src/test/ui/suggestions/attribute-typos.rs
index 74f63f2..7c8231b 100644
--- a/src/test/ui/suggestions/attribute-typos.rs
+++ b/src/test/ui/suggestions/attribute-typos.rs
@@ -1,11 +1,11 @@
-#[deprcated] //~ ERROR cannot find attribute macro `deprcated` in this scope
+#[deprcated] //~ ERROR cannot find attribute `deprcated` in this scope
 fn foo() {}
 
-#[tests] //~ ERROR cannot find attribute macro `tests` in this scope
+#[tests] //~ ERROR cannot find attribute `tests` in this scope
 fn bar() {}
 
 #[rustc_err]
-//~^ ERROR cannot find attribute macro `rustc_err` in this scope
+//~^ ERROR cannot find attribute `rustc_err` in this scope
 //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
 
 fn main() {}
diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr
index 6b2f591..e403293 100644
--- a/src/test/ui/suggestions/attribute-typos.stderr
+++ b/src/test/ui/suggestions/attribute-typos.stderr
@@ -7,19 +7,19 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-error: cannot find attribute macro `rustc_err` in this scope
+error: cannot find attribute `rustc_err` in this scope
   --> $DIR/attribute-typos.rs:7:3
    |
 LL | #[rustc_err]
    |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error`
 
-error: cannot find attribute macro `tests` in this scope
+error: cannot find attribute `tests` in this scope
   --> $DIR/attribute-typos.rs:4:3
    |
 LL | #[tests]
    |   ^^^^^ help: an attribute macro with a similar name exists: `test`
 
-error: cannot find attribute macro `deprcated` in this scope
+error: cannot find attribute `deprcated` in this scope
   --> $DIR/attribute-typos.rs:1:3
    |
 LL | #[deprcated]
diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
new file mode 100644
index 0000000..acd149c
--- /dev/null
+++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs
@@ -0,0 +1,18 @@
+// edition:2018
+trait T {
+    type O;
+}
+
+struct S;
+
+impl T for S {
+    type O = ();
+}
+
+fn foo() -> impl T<O=()> { S }
+
+fn bar(f: impl T<O=()>) {}
+
+fn main() {
+    bar(foo); //~ERROR E0277
+}
diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
new file mode 100644
index 0000000..2cc4653
--- /dev/null
+++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `fn() -> impl T {foo}: T` is not satisfied
+  --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:5
+   |
+LL | fn bar(f: impl T<O=()>) {}
+   | ----------------------- required by `bar`
+...
+LL |     bar(foo);
+   |     ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
+   |
+   = help: use parentheses to call the function: `foo()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
index 48c2503..4aec720 100644
--- a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
+++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr
@@ -2,7 +2,7 @@
   --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9
    |
 LL |     foo.hello();
-   |         ^^^^^
+   |         ^^^^^ method not found in `impl Foo`
    |
    = help: items from traits can only be used if the type parameter is bounded by the trait
 help: the following trait defines an item `hello`, perhaps you need to restrict type parameter `impl Foo` with it:
diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr
index 3e28700..da5aeb6 100644
--- a/src/test/ui/suggestions/into-str.stderr
+++ b/src/test/ui/suggestions/into-str.stderr
@@ -1,16 +1,14 @@
 error[E0277]: the trait bound `&str: std::convert::From<std::string::String>` is not satisfied
   --> $DIR/into-str.rs:4:5
    |
+LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {}
+   | ------------------------------------------- required by `foo`
+...
 LL |     foo(String::new());
    |     ^^^ the trait `std::convert::From<std::string::String>` is not implemented for `&str`
    |
    = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix
    = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String`
-note: required by `foo`
-  --> $DIR/into-str.rs:1:1
-   |
-LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/issue-21673.stderr b/src/test/ui/suggestions/issue-21673.stderr
index 6cf71c8..f2496f6 100644
--- a/src/test/ui/suggestions/issue-21673.stderr
+++ b/src/test/ui/suggestions/issue-21673.stderr
@@ -2,7 +2,7 @@
   --> $DIR/issue-21673.rs:6:7
    |
 LL |     x.method()
-   |       ^^^^^^
+   |       ^^^^^^ method not found in `&T`
    |
    = help: items from traits can only be used if the type parameter is bounded by the trait
 help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it:
@@ -14,7 +14,7 @@
   --> $DIR/issue-21673.rs:10:7
    |
 LL |     x.method()
-   |       ^^^^^^
+   |       ^^^^^^ method not found in `T`
    |
    = help: items from traits can only be used if the type parameter is bounded by the trait
 help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it:
diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr
index 3c9ea05..450cbd4 100644
--- a/src/test/ui/suggestions/opaque-type-error.stderr
+++ b/src/test/ui/suggestions/opaque-type-error.stderr
@@ -10,8 +10,8 @@
 LL | |     }.await
    | |_____- if and else have incompatible types
    |
-   = note: expected type `impl std::future::Future` (opaque type)
-              found type `impl std::future::Future` (opaque type)
+   = note: expected type `impl std::future::Future` (opaque type at <$DIR/opaque-type-error.rs:8:19>)
+              found type `impl std::future::Future` (opaque type at <$DIR/opaque-type-error.rs:12:19>)
    = note: distinct uses of `impl Trait` result in different opaque types
    = help: if both `Future`s have the same `Output` type, consider `.await`ing on both of them
 
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr
index ad4a4de..4678410 100644
--- a/src/test/ui/suggestions/suggest-methods.stderr
+++ b/src/test/ui/suggestions/suggest-methods.stderr
@@ -23,7 +23,7 @@
   --> $DIR/suggest-methods.rs:28:19
    |
 LL |     let _ = 63u32.count_o();
-   |                   ^^^^^^^
+   |                   ^^^^^^^ method not found in `u32`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/syntax-extension-minor.rs b/src/test/ui/syntax-extension-minor.rs
index 0206a76..2d6710a 100644
--- a/src/test/ui/syntax-extension-minor.rs
+++ b/src/test/ui/syntax-extension-minor.rs
@@ -1,3 +1,5 @@
+// run-pass
+
 #![feature(concat_idents)]
 
 pub fn main() {
@@ -5,10 +7,8 @@
     let _: concat_idents!(F, oo) = Foo; // Test that `concat_idents!` can be used in type positions
 
     let asdf_fdsa = "<.<".to_string();
-    // this now fails (correctly, I claim) because hygiene prevents
-    // the assembled identifier from being a reference to the binding.
+    // concat_idents should have call-site hygiene.
     assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
-    //~^ ERROR cannot find value `asdf_fdsa` in this scope
 
     assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction");
 }
diff --git a/src/test/ui/syntax-extension-minor.stderr b/src/test/ui/syntax-extension-minor.stderr
deleted file mode 100644
index 2d8056d..0000000
--- a/src/test/ui/syntax-extension-minor.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find value `asdf_fdsa` in this scope
-  --> $DIR/syntax-extension-minor.rs:10:13
-   |
-LL |     assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/test-shadowing/auxiliary/test_macro.rs b/src/test/ui/test-attrs/auxiliary/test_macro.rs
similarity index 100%
rename from src/test/ui/test-shadowing/auxiliary/test_macro.rs
rename to src/test/ui/test-attrs/auxiliary/test_macro.rs
diff --git a/src/test/ui/test-attrs/decl-macro-test.rs b/src/test/ui/test-attrs/decl-macro-test.rs
new file mode 100644
index 0000000..fcbe9f4
--- /dev/null
+++ b/src/test/ui/test-attrs/decl-macro-test.rs
@@ -0,0 +1,22 @@
+// Check that declarative macros can declare tests
+
+// check-pass
+// compile-flags: --test
+
+#![feature(decl_macro)]
+
+macro create_test() {
+    #[test]
+    fn test() {}
+}
+
+macro create_module_test() {
+    mod x {
+        #[test]
+        fn test() {}
+    }
+}
+
+create_test!();
+create_test!();
+create_module_test!();
diff --git a/src/test/ui/test-attrs/inaccessible-test-modules.rs b/src/test/ui/test-attrs/inaccessible-test-modules.rs
new file mode 100644
index 0000000..f5b3479
--- /dev/null
+++ b/src/test/ui/test-attrs/inaccessible-test-modules.rs
@@ -0,0 +1,9 @@
+// compile-flags:--test
+
+// the `--test` harness creates modules with these textual names, but
+// they should be inaccessible from normal code.
+use main as x; //~ ERROR unresolved import `main`
+use test as y; //~ ERROR unresolved import `test`
+
+#[test]
+fn baz() {}
diff --git a/src/test/ui/test-attrs/inaccessible-test-modules.stderr b/src/test/ui/test-attrs/inaccessible-test-modules.stderr
new file mode 100644
index 0000000..a94ea1e
--- /dev/null
+++ b/src/test/ui/test-attrs/inaccessible-test-modules.stderr
@@ -0,0 +1,21 @@
+error[E0432]: unresolved import `main`
+  --> $DIR/inaccessible-test-modules.rs:5:5
+   |
+LL | use main as x;
+   |     ----^^^^^
+   |     |
+   |     no `main` in the root
+   |     help: a similar name exists in the module: `main`
+
+error[E0432]: unresolved import `test`
+  --> $DIR/inaccessible-test-modules.rs:6:5
+   |
+LL | use test as y;
+   |     ----^^^^^
+   |     |
+   |     no `test` in the root
+   |     help: a similar name exists in the module: `test`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/test-allow-fail-attr.rs b/src/test/ui/test-attrs/test-allow-fail-attr.rs
similarity index 100%
rename from src/test/ui/test-allow-fail-attr.rs
rename to src/test/ui/test-attrs/test-allow-fail-attr.rs
diff --git a/src/test/ui/test-attr-non-associated-functions.rs b/src/test/ui/test-attrs/test-attr-non-associated-functions.rs
similarity index 100%
rename from src/test/ui/test-attr-non-associated-functions.rs
rename to src/test/ui/test-attrs/test-attr-non-associated-functions.rs
diff --git a/src/test/ui/test-attr-non-associated-functions.stderr b/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr
similarity index 100%
rename from src/test/ui/test-attr-non-associated-functions.stderr
rename to src/test/ui/test-attrs/test-attr-non-associated-functions.stderr
diff --git a/src/test/ui/test-shadowing/test-cant-be-shadowed.rs b/src/test/ui/test-attrs/test-cant-be-shadowed.rs
similarity index 100%
rename from src/test/ui/test-shadowing/test-cant-be-shadowed.rs
rename to src/test/ui/test-attrs/test-cant-be-shadowed.rs
diff --git a/src/test/ui/test-fn-signature-verification-for-explicit-return-type.rs b/src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs
similarity index 100%
rename from src/test/ui/test-fn-signature-verification-for-explicit-return-type.rs
rename to src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs
diff --git a/src/test/ui/test-main-not-dead-attr.rs b/src/test/ui/test-attrs/test-main-not-dead-attr.rs
similarity index 100%
rename from src/test/ui/test-main-not-dead-attr.rs
rename to src/test/ui/test-attrs/test-main-not-dead-attr.rs
diff --git a/src/test/ui/test-main-not-dead.rs b/src/test/ui/test-attrs/test-main-not-dead.rs
similarity index 100%
rename from src/test/ui/test-main-not-dead.rs
rename to src/test/ui/test-attrs/test-main-not-dead.rs
diff --git a/src/test/ui/test-on-macro.rs b/src/test/ui/test-attrs/test-on-macro.rs
similarity index 100%
rename from src/test/ui/test-on-macro.rs
rename to src/test/ui/test-attrs/test-on-macro.rs
diff --git a/src/test/ui/test-on-macro.stderr b/src/test/ui/test-attrs/test-on-macro.stderr
similarity index 100%
rename from src/test/ui/test-on-macro.stderr
rename to src/test/ui/test-attrs/test-on-macro.stderr
diff --git a/src/test/ui/test-runner-hides-buried-main.rs b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs
similarity index 100%
rename from src/test/ui/test-runner-hides-buried-main.rs
rename to src/test/ui/test-attrs/test-runner-hides-buried-main.rs
diff --git a/src/test/ui/test-runner-hides-main.rs b/src/test/ui/test-attrs/test-runner-hides-main.rs
similarity index 100%
rename from src/test/ui/test-runner-hides-main.rs
rename to src/test/ui/test-attrs/test-runner-hides-main.rs
diff --git a/src/test/ui/test-runner-hides-start.rs b/src/test/ui/test-attrs/test-runner-hides-start.rs
similarity index 100%
rename from src/test/ui/test-runner-hides-start.rs
rename to src/test/ui/test-attrs/test-runner-hides-start.rs
diff --git a/src/test/ui/test-should-fail-good-message.rs b/src/test/ui/test-attrs/test-should-fail-good-message.rs
similarity index 100%
rename from src/test/ui/test-should-fail-good-message.rs
rename to src/test/ui/test-attrs/test-should-fail-good-message.rs
diff --git a/src/test/ui/test-should-panic-attr.rs b/src/test/ui/test-attrs/test-should-panic-attr.rs
similarity index 100%
rename from src/test/ui/test-should-panic-attr.rs
rename to src/test/ui/test-attrs/test-should-panic-attr.rs
diff --git a/src/test/ui/test-should-panic-attr.stderr b/src/test/ui/test-attrs/test-should-panic-attr.stderr
similarity index 100%
rename from src/test/ui/test-should-panic-attr.stderr
rename to src/test/ui/test-attrs/test-should-panic-attr.stderr
diff --git a/src/test/ui/test-vs-cfg-test.rs b/src/test/ui/test-attrs/test-vs-cfg-test.rs
similarity index 100%
rename from src/test/ui/test-vs-cfg-test.rs
rename to src/test/ui/test-attrs/test-vs-cfg-test.rs
diff --git a/src/test/ui/test-warns-dead-code.rs b/src/test/ui/test-attrs/test-warns-dead-code.rs
similarity index 100%
rename from src/test/ui/test-warns-dead-code.rs
rename to src/test/ui/test-attrs/test-warns-dead-code.rs
diff --git a/src/test/ui/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr
similarity index 100%
rename from src/test/ui/test-warns-dead-code.stderr
rename to src/test/ui/test-attrs/test-warns-dead-code.stderr
diff --git a/src/test/ui/tool-attributes/diagnostic_item.rs b/src/test/ui/tool-attributes/diagnostic_item.rs
index 1d35422..26a52ce 100644
--- a/src/test/ui/tool-attributes/diagnostic_item.rs
+++ b/src/test/ui/tool-attributes/diagnostic_item.rs
@@ -1,2 +1,3 @@
 #[rustc_diagnostic_item = "foomp"] //~ ERROR compiler internal support for linting
 struct Foomp;
+fn main() {}
diff --git a/src/test/ui/tool-attributes/diagnostic_item.stderr b/src/test/ui/tool-attributes/diagnostic_item.stderr
index deff4da..5432f8d 100644
--- a/src/test/ui/tool-attributes/diagnostic_item.stderr
+++ b/src/test/ui/tool-attributes/diagnostic_item.stderr
@@ -7,11 +7,6 @@
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-error[E0601]: `main` function not found in crate `diagnostic_item`
-   |
-   = note: consider adding a `main` function to `$DIR/diagnostic_item.rs`
+error: aborting due to previous error
 
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0601, E0658.
-For more information about an error, try `rustc --explain E0601`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
index 8c62b34..d5698be 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
@@ -4,14 +4,14 @@
 #[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
 struct S;
 
-// Interpreted as a feature gated custom attribute
-#[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
+// Interpreted as an unstable custom attribute
+#[rustfmt] //~ ERROR cannot find attribute `rustfmt` in this scope
 fn check() {}
 
 #[rustfmt::skip] // OK
 fn main() {
     rustfmt; //~ ERROR expected value, found tool module `rustfmt`
-    rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
+    rustfmt!(); //~ ERROR cannot find macro `rustfmt` in this scope
 
     rustfmt::skip; //~ ERROR expected value, found tool attribute `rustfmt::skip`
 }
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
index 33581a1..6bef793 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
@@ -4,13 +4,13 @@
 LL | #[derive(rustfmt)]
    |          ^^^^^^^
 
-error: cannot find attribute macro `rustfmt` in this scope
+error: cannot find attribute `rustfmt` in this scope
   --> $DIR/tool-attributes-misplaced-1.rs:8:3
    |
 LL | #[rustfmt]
    |   ^^^^^^^
 
-error: cannot find macro `rustfmt!` in this scope
+error: cannot find macro `rustfmt` in this scope
   --> $DIR/tool-attributes-misplaced-1.rs:14:5
    |
 LL |     rustfmt!();
diff --git a/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr
index 972d213..8403b2e 100644
--- a/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr
+++ b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr
@@ -1,28 +1,24 @@
 error[E0277]: `std::rc::Rc<u32>` cannot be sent between threads safely
   --> $DIR/trait-alias-cross-crate.rs:14:5
    |
+LL | fn use_alias<T: SendSync>() {}
+   | --------------------------- required by `use_alias`
+...
 LL |     use_alias::<Rc<u32>>();
    |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<u32>`
-note: required by `use_alias`
-  --> $DIR/trait-alias-cross-crate.rs:10:1
-   |
-LL | fn use_alias<T: SendSync>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::rc::Rc<u32>` cannot be shared between threads safely
   --> $DIR/trait-alias-cross-crate.rs:14:5
    |
+LL | fn use_alias<T: SendSync>() {}
+   | --------------------------- required by `use_alias`
+...
 LL |     use_alias::<Rc<u32>>();
    |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc<u32>`
-note: required by `use_alias`
-  --> $DIR/trait-alias-cross-crate.rs:10:1
-   |
-LL | fn use_alias<T: SendSync>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs
index fb26b7e..1440f02 100644
--- a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs
+++ b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 // This test checks that trait objects involving trait aliases are well-formed.
 
diff --git a/src/test/ui/traits/trait-alias/trait-alias-wf.stderr b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr
index ee2dd5b..ca6d058 100644
--- a/src/test/ui/traits/trait-alias/trait-alias-wf.stderr
+++ b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr
@@ -1,15 +1,12 @@
 error[E0277]: the trait bound `T: Foo` is not satisfied
   --> $DIR/trait-alias-wf.rs:5:1
    |
+LL | trait A<T: Foo> {}
+   | --------------- required by `A`
 LL | trait B<T> = A<T>;
    | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T`
    |
    = help: consider adding a `where T: Foo` bound
-note: required by `A`
-  --> $DIR/trait-alias-wf.rs:4:1
-   |
-LL | trait A<T: Foo> {}
-   | ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr
index 6fdd2ce..3c68d46 100644
--- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr
@@ -1,26 +1,20 @@
 error[E0277]: the trait bound `u32: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:13:1
    |
+LL | struct Foo<T:Trait> {
+   | ------------------- required by `Foo`
+...
 LL | fn explode(x: Foo<u32>) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u32`
-   |
-note: required by `Foo`
-  --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:3:1
-   |
-LL | struct Foo<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `f32: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:16:1
    |
+LL | enum Bar<T:Trait> {
+   | ----------------- required by `Bar`
+...
 LL | fn kaboom(y: Bar<f32>) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `f32`
-   |
-note: required by `Bar`
-  --> $DIR/trait-bounds-on-structs-and-enums-in-fns.rs:7:1
-   |
-LL | enum Bar<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr
index 15441b5..7e8db61 100644
--- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `u16: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums-in-impls.rs:20:6
    |
+LL | struct Foo<T:Trait> {
+   | ------------------- required by `Foo`
+...
 LL | impl PolyTrait<Foo<u16>> for Struct {
    |      ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16`
-   |
-note: required by `Foo`
-  --> $DIR/trait-bounds-on-structs-and-enums-in-impls.rs:3:1
-   |
-LL | struct Foo<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr
index cdcfff9..070b7b0 100644
--- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr
@@ -1,26 +1,20 @@
 error[E0277]: the trait bound `usize: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:15:14
    |
+LL | struct Foo<T:Trait> {
+   | ------------------- required by `Foo`
+...
 LL |     let baz: Foo<usize> = loop { };
    |              ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
-   |
-note: required by `Foo`
-  --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:5:1
-   |
-LL | struct Foo<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `{integer}: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:10:15
    |
+LL | struct Foo<T:Trait> {
+   | ------------------- required by `Foo`
+...
 LL |     let foo = Foo {
    |               ^^^ the trait `Trait` is not implemented for `{integer}`
-   |
-note: required by `Foo`
-  --> $DIR/trait-bounds-on-structs-and-enums-locals.rs:5:1
-   |
-LL | struct Foo<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr
index b019c29..722f017 100644
--- a/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `usize: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums-static.rs:9:11
    |
+LL | struct Foo<T:Trait> {
+   | ------------------- required by `Foo`
+...
 LL | static X: Foo<usize> = Foo {
    |           ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
-   |
-note: required by `Foo`
-  --> $DIR/trait-bounds-on-structs-and-enums-static.rs:5:1
-   |
-LL | struct Foo<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr
index 9a4cc90..bd76df8 100644
--- a/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr
+++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr
@@ -1,89 +1,71 @@
 error[E0277]: the trait bound `T: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums.rs:13:9
    |
+LL | struct Foo<T:Trait> {
+   | ------------------- required by `Foo`
+...
 LL | impl<T> Foo<T> {
    |         ^^^^^^ the trait `Trait` is not implemented for `T`
    |
    = help: consider adding a `where T: Trait` bound
-note: required by `Foo`
-  --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1
-   |
-LL | struct Foo<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `isize: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums.rs:19:5
    |
+LL | struct Foo<T:Trait> {
+   | ------------------- required by `Foo`
+...
 LL |     a: Foo<isize>,
    |     ^^^^^^^^^^^^^ the trait `Trait` is not implemented for `isize`
-   |
-note: required by `Foo`
-  --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1
-   |
-LL | struct Foo<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `usize: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums.rs:23:10
    |
+LL | enum Bar<T:Trait> {
+   | ----------------- required by `Bar`
+...
 LL |     Quux(Bar<usize>),
    |          ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
-   |
-note: required by `Bar`
-  --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1
-   |
-LL | enum Bar<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `U: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums.rs:27:5
    |
+LL | struct Foo<T:Trait> {
+   | ------------------- required by `Foo`
+...
 LL |     b: Foo<U>,
    |     ^^^^^^^^^ the trait `Trait` is not implemented for `U`
    |
    = help: consider adding a `where U: Trait` bound
-note: required by `Foo`
-  --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1
-   |
-LL | struct Foo<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `V: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums.rs:31:21
    |
+LL | enum Bar<T:Trait> {
+   | ----------------- required by `Bar`
+...
 LL |     EvenMoreBadness(Bar<V>),
    |                     ^^^^^^ the trait `Trait` is not implemented for `V`
    |
    = help: consider adding a `where V: Trait` bound
-note: required by `Bar`
-  --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1
-   |
-LL | enum Bar<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `i32: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums.rs:35:5
    |
+LL | struct Foo<T:Trait> {
+   | ------------------- required by `Foo`
+...
 LL |     Foo<i32>,
    |     ^^^^^^^^ the trait `Trait` is not implemented for `i32`
-   |
-note: required by `Foo`
-  --> $DIR/trait-bounds-on-structs-and-enums.rs:3:1
-   |
-LL | struct Foo<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `u8: Trait` is not satisfied
   --> $DIR/trait-bounds-on-structs-and-enums.rs:39:22
    |
+LL | enum Bar<T:Trait> {
+   | ----------------- required by `Bar`
+...
 LL |     DictionaryLike { field: Bar<u8> },
    |                      ^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u8`
-   |
-note: required by `Bar`
-  --> $DIR/trait-bounds-on-structs-and-enums.rs:7:1
-   |
-LL | enum Bar<T:Trait> {
-   | ^^^^^^^^^^^^^^^^^
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/traits/trait-impl-1.stderr b/src/test/ui/traits/trait-impl-1.stderr
index 71d5cc2..0d61c3e 100644
--- a/src/test/ui/traits/trait-impl-1.stderr
+++ b/src/test/ui/traits/trait-impl-1.stderr
@@ -2,7 +2,7 @@
   --> $DIR/trait-impl-1.rs:15:7
    |
 LL |     x.foo();
-   |       ^^^
+   |       ^^^ method not found in `&i32`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr
index de699a6..39cc66d 100644
--- a/src/test/ui/traits/trait-item-privacy.stderr
+++ b/src/test/ui/traits/trait-item-privacy.stderr
@@ -5,7 +5,7 @@
    | --------- method `a` not found for this
 ...
 LL |     S.a();
-   |       ^
+   |       ^ method not found in `S`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `a`, perhaps you need to implement it:
@@ -17,8 +17,15 @@
 LL | struct S;
    | --------- method `b` not found for this
 ...
+LL |         fn b(&self) { }
+   |            -
+   |            |
+   |            the method is available for `std::boxed::Box<S>` here
+   |            the method is available for `std::sync::Arc<S>` here
+   |            the method is available for `std::rc::Rc<S>` here
+...
 LL |     S.b();
-   |       ^
+   |       ^ method not found in `S`
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope, perhaps add a `use` for it:
@@ -103,12 +110,17 @@
 error[E0038]: the trait `assoc_const::C` cannot be made into an object
   --> $DIR/trait-item-privacy.rs:101:5
    |
+LL |         const A: u8 = 0;
+   |               - the trait cannot contain associated consts like `A`
+...
+LL |         const B: u8 = 0;
+   |               - the trait cannot contain associated consts like `B`
+...
+LL |         const C: u8 = 0;
+   |               - the trait cannot contain associated consts like `C`
+...
 LL |     C::A;
    |     ^^^^ the trait `assoc_const::C` cannot be made into an object
-   |
-   = note: the trait cannot contain associated consts like `C`
-   = note: the trait cannot contain associated consts like `B`
-   = note: the trait cannot contain associated consts like `A`
 
 error[E0223]: ambiguous associated type
   --> $DIR/trait-item-privacy.rs:115:12
diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr
index 68edc17..3ac1e96 100644
--- a/src/test/ui/traits/trait-object-safety.stderr
+++ b/src/test/ui/traits/trait-object-safety.stderr
@@ -1,19 +1,22 @@
 error[E0038]: the trait `Tr` cannot be made into an object
   --> $DIR/trait-object-safety.rs:15:22
    |
+LL |     fn foo();
+   |        --- associated function `foo` has no `self` parameter
+...
 LL |     let _: &dyn Tr = &St;
    |                      ^^^ the trait `Tr` cannot be made into an object
    |
-   = note: method `foo` has no receiver
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St`
 
 error[E0038]: the trait `Tr` cannot be made into an object
   --> $DIR/trait-object-safety.rs:15:12
    |
+LL |     fn foo();
+   |        --- associated function `foo` has no `self` parameter
+...
 LL |     let _: &dyn Tr = &St;
    |            ^^^^^^^ the trait `Tr` cannot be made into an object
-   |
-   = note: method `foo` has no receiver
 
 error: aborting due to 2 previous errors
 
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 390d21c..a99536d 100644
--- a/src/test/ui/traits/trait-static-method-generic-inference.stderr
+++ b/src/test/ui/traits/trait-static-method-generic-inference.stderr
@@ -1,14 +1,11 @@
 error[E0283]: type annotations required: cannot resolve `_: base::HasNew<base::Foo>`
   --> $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();
    |                         ^^^^^^^^^^^^^^^^^
-   |
-note: required by `base::HasNew::new`
-  --> $DIR/trait-static-method-generic-inference.rs:8:9
-   |
-LL |         fn new() -> T;
-   |         ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr
index 5d52519..83c2c06 100644
--- a/src/test/ui/traits/trait-test-2.stderr
+++ b/src/test/ui/traits/trait-test-2.stderr
@@ -13,20 +13,25 @@
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/trait-test-2.rs:11:16
    |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+   |                ---                    ---- method `blah` has generic type parameters
+   |                |
+   |                method `dup` references the `Self` type in its parameters or return type
+...
 LL |     (box 10 as Box<dyn bar>).dup();
    |                ^^^^^^^^^^^^ the trait `bar` cannot be made into an object
-   |
-   = note: method `dup` references the `Self` type in its arguments or return type
-   = note: method `blah` has generic type parameters
 
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/trait-test-2.rs:11:6
    |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+   |                ---                    ---- method `blah` has generic type parameters
+   |                |
+   |                method `dup` references the `Self` type in its parameters or return type
+...
 LL |     (box 10 as Box<dyn bar>).dup();
    |      ^^^^^^ the trait `bar` cannot be made into an object
    |
-   = note: method `dup` references the `Self` type in its arguments or return type
-   = note: method `blah` has generic type parameters
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn bar>>` for `std::boxed::Box<{integer}>`
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr b/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr
index cd8501e..b29d726 100644
--- a/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr
+++ b/src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr
@@ -1,15 +1,13 @@
 error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum`
   --> $DIR/traits-inductive-overflow-simultaneous.rs:18:5
    |
+LL | fn is_ee<T: Combo>(t: T) {
+   | ------------------------ required by `is_ee`
+...
 LL |     is_ee(4);
    |     ^^^^^
    |
    = note: required because of the requirements on the impl of `Combo` for `{integer}`
-note: required by `is_ee`
-  --> $DIR/traits-inductive-overflow-simultaneous.rs:13:1
-   |
-LL | fn is_ee<T: Combo>(t: T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
index 87e7ba3..0b54361 100644
--- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
+++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
@@ -7,15 +7,13 @@
 error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied
   --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:18
    |
+LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+   | --------------------------------- required by `copy`
+...
 LL |     let (a, b) = copy(NoClone);
    |                  ^^^^ the trait `std::marker::Copy` is not implemented for `NoClone`
    |
    = note: required because of the requirements on the impl of `Magic` for `NoClone`
-note: required by `copy`
-  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:9:1
-   |
-LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr
index 769582a..92747be 100644
--- a/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr
+++ b/src/test/ui/traits/traits-inductive-overflow-supertrait.stderr
@@ -1,15 +1,13 @@
 error[E0275]: overflow evaluating the requirement `NoClone: Magic`
   --> $DIR/traits-inductive-overflow-supertrait.rs:13:18
    |
+LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
+   | --------------------------------- required by `copy`
+...
 LL |     let (a, b) = copy(NoClone);
    |                  ^^^^
    |
    = note: required because of the requirements on the impl of `Magic` for `NoClone`
-note: required by `copy`
-  --> $DIR/traits-inductive-overflow-supertrait.rs:7:1
-   |
-LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr
index 61adbf0..58d7fcd 100644
--- a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr
+++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr
@@ -1,14 +1,11 @@
 error[E0275]: overflow evaluating the requirement `*mut (): Magic`
   --> $DIR/traits-inductive-overflow-two-traits.rs:19:5
    |
+LL | fn wizard<T: Magic>() { check::<<T as Magic>::X>(); }
+   | --------------------- required by `wizard`
+...
 LL |     wizard::<*mut ()>();
    |     ^^^^^^^^^^^^^^^^^
-   |
-note: required by `wizard`
-  --> $DIR/traits-inductive-overflow-two-traits.rs:16:1
-   |
-LL | fn wizard<T: Magic>() { check::<<T as Magic>::X>(); }
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/traits-negative-impls.stderr b/src/test/ui/traits/traits-negative-impls.stderr
index 1bdd73e..23bd334 100644
--- a/src/test/ui/traits/traits-negative-impls.stderr
+++ b/src/test/ui/traits/traits-negative-impls.stderr
@@ -1,74 +1,67 @@
 error[E0277]: `dummy::TestType` cannot be sent between threads safely
   --> $DIR/traits-negative-impls.rs:23:5
    |
+LL | struct Outer<T: Send>(T);
+   | ------------------------- required by `Outer`
+...
 LL |     Outer(TestType);
    |     ^^^^^ `dummy::TestType` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
-note: required by `Outer`
-  --> $DIR/traits-negative-impls.rs:10:1
-   |
-LL | struct Outer<T: Send>(T);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dummy::TestType` cannot be sent between threads safely
   --> $DIR/traits-negative-impls.rs:23:5
    |
+LL | struct Outer<T: Send>(T);
+   | ------------------------- required by `Outer`
+...
 LL |     Outer(TestType);
    |     ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `dummy::TestType`
-note: required by `Outer`
-  --> $DIR/traits-negative-impls.rs:10:1
-   |
-LL | struct Outer<T: Send>(T);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dummy1b::TestType` cannot be sent between threads safely
   --> $DIR/traits-negative-impls.rs:32:5
    |
+LL | fn is_send<T: Send>(_: T) {}
+   | ------------------------- required by `is_send`
+...
 LL |     is_send(TestType);
    |     ^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `dummy1b::TestType`
-note: required by `is_send`
-  --> $DIR/traits-negative-impls.rs:16:1
-   |
-LL | fn is_send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dummy1c::TestType` cannot be sent between threads safely
   --> $DIR/traits-negative-impls.rs:40:5
    |
+LL | fn is_send<T: Send>(_: T) {}
+   | ------------------------- required by `is_send`
+...
 LL |     is_send((8, TestType));
    |     ^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
    |
    = help: within `({integer}, dummy1c::TestType)`, the trait `std::marker::Send` is not implemented for `dummy1c::TestType`
    = note: required because it appears within the type `({integer}, dummy1c::TestType)`
-note: required by `is_send`
-  --> $DIR/traits-negative-impls.rs:16:1
-   |
-LL | fn is_send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dummy2::TestType` cannot be sent between threads safely
   --> $DIR/traits-negative-impls.rs:48:5
    |
+LL | fn is_send<T: Send>(_: T) {}
+   | ------------------------- required by `is_send`
+...
 LL |     is_send(Box::new(TestType));
    |     ^^^^^^^ `dummy2::TestType` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `dummy2::TestType`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dummy2::TestType>`
    = note: required because it appears within the type `std::boxed::Box<dummy2::TestType>`
-note: required by `is_send`
-  --> $DIR/traits-negative-impls.rs:16:1
-   |
-LL | fn is_send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `dummy3::TestType` cannot be sent between threads safely
   --> $DIR/traits-negative-impls.rs:56:5
    |
+LL | fn is_send<T: Send>(_: T) {}
+   | ------------------------- required by `is_send`
+...
 LL |     is_send(Box::new(Outer2(TestType)));
    |     ^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
    |
@@ -76,25 +69,18 @@
    = note: required because it appears within the type `Outer2<dummy3::TestType>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<Outer2<dummy3::TestType>>`
    = note: required because it appears within the type `std::boxed::Box<Outer2<dummy3::TestType>>`
-note: required by `is_send`
-  --> $DIR/traits-negative-impls.rs:16:1
-   |
-LL | fn is_send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `main::TestType` cannot be sent between threads safely
   --> $DIR/traits-negative-impls.rs:66:5
    |
+LL | fn is_sync<T: Sync>(_: T) {}
+   | ------------------------- required by `is_sync`
+...
 LL |     is_sync(Outer2(TestType));
    |     ^^^^^^^ `main::TestType` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `main::TestType`
    = note: required because of the requirements on the impl of `std::marker::Sync` for `Outer2<main::TestType>`
-note: required by `is_sync`
-  --> $DIR/traits-negative-impls.rs:17:1
-   |
-LL | fn is_sync<T: Sync>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr
index 5d1c913..db77e82 100644
--- a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr
+++ b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr
@@ -15,27 +15,22 @@
 error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
   --> $DIR/traits-repeated-supertrait-ambig.rs:34:5
    |
+LL |     fn same_as(&self, t: T) -> bool;
+   |     -------------------------------- required by `CompareTo::same_as`
+...
 LL |     CompareToInts::same_as(c, 22)
    |     ^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
-   |
-note: required by `CompareTo::same_as`
-  --> $DIR/traits-repeated-supertrait-ambig.rs:9:5
-   |
-LL |     fn same_as(&self, t: T) -> bool;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
   --> $DIR/traits-repeated-supertrait-ambig.rs:38:5
    |
+LL |     fn same_as(&self, t: T) -> bool;
+   |     -------------------------------- required by `CompareTo::same_as`
+...
 LL |     CompareTo::same_as(c, 22)
    |     ^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
    |
    = help: consider adding a `where C: CompareTo<i32>` bound
-note: required by `CompareTo::same_as`
-  --> $DIR/traits-repeated-supertrait-ambig.rs:9:5
-   |
-LL |     fn same_as(&self, t: T) -> bool;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `i64: CompareTo<i32>` is not satisfied
   --> $DIR/traits-repeated-supertrait-ambig.rs:42:23
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
index 46b4b2a..d172d5e 100644
--- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
+++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
@@ -12,7 +12,7 @@
   --> $DIR/trivial-bounds-leak.rs:24:10
    |
 LL |     3i32.test();
-   |          ^^^^
+   |          ^^^^ method not found in `i32`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `test`, perhaps you need to implement it:
@@ -21,26 +21,20 @@
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/trivial-bounds-leak.rs:25:5
    |
+LL |     fn test(&self);
+   |     --------------- required by `Foo::test`
+...
 LL |     Foo::test(&4i32);
    |     ^^^^^^^^^ the trait `Foo` is not implemented for `i32`
-   |
-note: required by `Foo::test`
-  --> $DIR/trivial-bounds-leak.rs:5:5
-   |
-LL |     fn test(&self);
-   |     ^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/trivial-bounds-leak.rs:26:5
    |
 LL |     generic_function(5i32);
    |     ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
-   |
-note: required by `generic_function`
-  --> $DIR/trivial-bounds-leak.rs:29:1
-   |
+...
 LL | fn generic_function<T: Foo>(t: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | --------------------------------- required by `generic_function`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/try-block/try-block-opt-init.rs b/src/test/ui/try-block/try-block-opt-init.rs
index 2387db8..ef10b47 100644
--- a/src/test/ui/try-block/try-block-opt-init.rs
+++ b/src/test/ui/try-block/try-block-opt-init.rs
@@ -12,5 +12,5 @@
         Ok::<(), ()>(())?;
         use_val(cfg_res);
     };
-    assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly uninitialized variable: `cfg_res`
+    assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly-uninitialized variable: `cfg_res`
 }
diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr
index ec0128d..3089064 100644
--- a/src/test/ui/try-block/try-block-opt-init.stderr
+++ b/src/test/ui/try-block/try-block-opt-init.stderr
@@ -1,8 +1,8 @@
-error[E0381]: borrow of possibly uninitialized variable: `cfg_res`
+error[E0381]: borrow of possibly-uninitialized variable: `cfg_res`
   --> $DIR/try-block-opt-init.rs:15:5
    |
 LL |     assert_eq!(cfg_res, 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly uninitialized `cfg_res`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `cfg_res`
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr
index 9f120e0..6878cd8 100644
--- a/src/test/ui/try-operator-on-main.stderr
+++ b/src/test/ui/try-operator-on-main.stderr
@@ -21,12 +21,9 @@
    |
 LL |     try_trait_generic::<()>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Try` is not implemented for `()`
-   |
-note: required by `try_trait_generic`
-  --> $DIR/try-operator-on-main.rs:20:1
-   |
+...
 LL | fn try_trait_generic<T: Try>() -> T {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ----------------------------------- required by `try_trait_generic`
 
 error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
   --> $DIR/try-operator-on-main.rs:22:5
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs
index 0c21209..19fcc78 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs
@@ -9,13 +9,13 @@
 
 #![allow(irrefutable_let_patterns)]
 
-enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+enum Enum<T> { TSVariant(T), SVariant { _v: T }, UVariant }
 type Alias<T> = Enum<T>;
 type AliasFixed = Enum<()>;
 
 macro_rules! is_variant {
     (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr));
-    (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr));
+    (SVariant, $expr:expr) => (is_variant!(@check SVariant, { _v: _ }, $expr));
     (UVariant, $expr:expr) => (is_variant!(@check UVariant, {}, $expr));
     (@check $variant:ident, $matcher:tt, $expr:expr) => (
         assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false },
@@ -37,14 +37,14 @@
 
     // Struct variant
 
-    is_variant!(SVariant, Enum::SVariant { v: () });
-    is_variant!(SVariant, Enum::SVariant::<()> { v: () });
-    is_variant!(SVariant, Enum::<()>::SVariant { v: () });
+    is_variant!(SVariant, Enum::SVariant { _v: () });
+    is_variant!(SVariant, Enum::SVariant::<()> { _v: () });
+    is_variant!(SVariant, Enum::<()>::SVariant { _v: () });
 
-    is_variant!(SVariant, Alias::SVariant { v: () });
-    is_variant!(SVariant, Alias::<()>::SVariant { v: () });
+    is_variant!(SVariant, Alias::SVariant { _v: () });
+    is_variant!(SVariant, Alias::<()>::SVariant { _v: () });
 
-    is_variant!(SVariant, AliasFixed::SVariant { v: () });
+    is_variant!(SVariant, AliasFixed::SVariant { _v: () });
 
     // Unit variant
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs
index 91c4576..9e96b1c 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs
@@ -24,3 +24,5 @@
             .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
     }
 }
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
index ebb13fc..b838c06 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
@@ -1,7 +1,3 @@
-error[E0601]: `main` function not found in crate `issue_60564`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-60564.rs`
-
 error: type parameter `E` is part of concrete type but not used in parameter list for the `impl Trait` type alias
   --> $DIR/issue-60564.rs:20:49
    |
@@ -20,6 +16,5 @@
 LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/type/ascription/issue-34255-1.rs b/src/test/ui/type/ascription/issue-34255-1.rs
index c11a248..c21d9f3 100644
--- a/src/test/ui/type/ascription/issue-34255-1.rs
+++ b/src/test/ui/type/ascription/issue-34255-1.rs
@@ -13,3 +13,4 @@
 }
 
 // This case isn't currently being handled gracefully, including for completeness.
+fn main() {}
diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr
index 531455b..195b393 100644
--- a/src/test/ui/type/ascription/issue-34255-1.stderr
+++ b/src/test/ui/type/ascription/issue-34255-1.stderr
@@ -14,17 +14,13 @@
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
 
-error[E0601]: `main` function not found in crate `issue_34255_1`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-34255-1.rs`
-
 error[E0107]: wrong number of type arguments: expected 1, found 0
   --> $DIR/issue-34255-1.rs:7:22
    |
 LL |         input_cells: Vec::new()
    |                      ^^^^^^^^^^ expected 1 type argument
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0107, E0425, E0601.
+Some errors have detailed explanations: E0107, E0425.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/type/ascription/issue-54516.rs b/src/test/ui/type/ascription/issue-54516.rs
index 6d65760..b53bfe5 100644
--- a/src/test/ui/type/ascription/issue-54516.rs
+++ b/src/test/ui/type/ascription/issue-54516.rs
@@ -2,5 +2,5 @@
 
 fn main() {
     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
-    //~^ ERROR expected token: `,`
+    //~^ ERROR expected one of
 }
diff --git a/src/test/ui/type/ascription/issue-54516.stderr b/src/test/ui/type/ascription/issue-54516.stderr
index a846f3b..9794290 100644
--- a/src/test/ui/type/ascription/issue-54516.stderr
+++ b/src/test/ui/type/ascription/issue-54516.stderr
@@ -1,8 +1,8 @@
-error: expected token: `,`
+error: expected one of `!`, `,`, or `::`, found `(`
   --> $DIR/issue-54516.rs:4:58
    |
 LL |     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
-   |                            -                             ^ expected `,`
+   |                            -                             ^ expected one of `!`, `,`, or `::` here
    |                            |
    |                            help: maybe write a path separator here: `::`
    |
diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr
index 92ae974..1dd2aaf 100644
--- a/src/test/ui/type/type-annotation-needed.stderr
+++ b/src/test/ui/type/type-annotation-needed.stderr
@@ -1,14 +1,11 @@
 error[E0283]: type annotations required: cannot resolve `_: std::convert::Into<std::string::String>`
   --> $DIR/type-annotation-needed.rs:5:5
    |
+LL | fn foo<T: Into<String>>(x: i32) {}
+   | ------------------------------- required by `foo`
+...
 LL |     foo(42);
    |     ^^^
-   |
-note: required by `foo`
-  --> $DIR/type-annotation-needed.rs:1:1
-   |
-LL | fn foo<T: Into<String>>(x: i32) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr
index a46d79e..42cca76 100644
--- a/src/test/ui/type/type-check-defaults.stderr
+++ b/src/test/ui/type/type-check-defaults.stderr
@@ -1,90 +1,71 @@
 error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
   --> $DIR/type-check-defaults.rs:6:19
    |
+LL | struct 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>`
    |
    = help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
-note: required by `Foo`
-  --> $DIR/type-check-defaults.rs:5:1
-   |
-LL | struct Foo<T, U: FromIterator<T>>(T, U);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
   --> $DIR/type-check-defaults.rs:8:27
    |
+LL | struct 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>`
    |
    = help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
-note: required by `Foo`
-  --> $DIR/type-check-defaults.rs:5:1
-   |
-LL | struct Foo<T, U: FromIterator<T>>(T, U);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
   --> $DIR/type-check-defaults.rs:11:1
    |
 LL | struct Bounds<T:Copy=String>(T);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
-   |
-note: required by `Bounds`
-  --> $DIR/type-check-defaults.rs:11:1
-   |
-LL | struct Bounds<T:Copy=String>(T);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | the trait `std::marker::Copy` is not implemented for `std::string::String`
+   | required by `Bounds`
 
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
   --> $DIR/type-check-defaults.rs:14:1
    |
 LL | struct WhereClause<T=String>(T) where T: Copy;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
-   |
-note: required by `WhereClause`
-  --> $DIR/type-check-defaults.rs:14:1
-   |
-LL | struct WhereClause<T=String>(T) where T: Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | the trait `std::marker::Copy` is not implemented for `std::string::String`
+   | required by `WhereClause`
 
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
   --> $DIR/type-check-defaults.rs:17:1
    |
 LL | trait TraitBound<T:Copy=String> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
-   |
-note: required by `TraitBound`
-  --> $DIR/type-check-defaults.rs:17:1
-   |
-LL | trait TraitBound<T:Copy=String> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------^^^
+   | |
+   | the trait `std::marker::Copy` is not implemented for `std::string::String`
+   | required by `TraitBound`
 
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/type-check-defaults.rs:21:1
    |
+LL | trait Super<T: Copy> { }
+   | -------------------- required by `Super`
 LL | trait Base<T = String>: Super<T> { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `Super`
-  --> $DIR/type-check-defaults.rs:20:1
-   |
-LL | trait Super<T: Copy> { }
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: cannot add `u8` to `i32`
   --> $DIR/type-check-defaults.rs:24:1
    |
 LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
+   | ------------------------------------------------------------------------^^^
+   | |
+   | no implementation for `i32 + u8`
+   | required by `ProjectionPred`
    |
    = help: the trait `std::ops::Add<u8>` is not implemented for `i32`
-note: required by `ProjectionPred`
-  --> $DIR/type-check-defaults.rs:24:1
-   |
-LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr
index 254875f..732a81c 100644
--- a/src/test/ui/type/type-check/issue-40294.stderr
+++ b/src/test/ui/type/type-check/issue-40294.stderr
@@ -1,6 +1,9 @@
 error[E0283]: type annotations required: cannot resolve `&'a T: Foo`
   --> $DIR/issue-40294.rs:5:1
    |
+LL |   trait Foo: Sized {
+   |   ---------------- required by `Foo`
+...
 LL | / fn foo<'a,'b,T>(x: &'a T, y: &'b T)
 LL | |     where &'a T : Foo,
 LL | |           &'b T : Foo
@@ -9,12 +12,6 @@
 LL | |     y.foo();
 LL | | }
    | |_^
-   |
-note: required by `Foo`
-  --> $DIR/issue-40294.rs:1:1
-   |
-LL | trait Foo: Sized {
-   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
index 58727ea..b315fe9 100644
--- a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
+++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
@@ -13,10 +13,11 @@
 error[E0038]: the trait `MyAdd` cannot be made into an object
   --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18
    |
+LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
+   |                            --- method `add` references the `Self` type in its parameters or return type
+...
 LL |     let y = x as dyn MyAdd<i32>;
    |                  ^^^^^^^^^^^^^^ the trait `MyAdd` cannot be made into an object
-   |
-   = note: method `add` references the `Self` type in its arguments or return type
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr
index 15db94e..7d4bbc8 100644
--- a/src/test/ui/type/type-params-in-different-spaces-2.stderr
+++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr
@@ -1,28 +1,24 @@
 error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
   --> $DIR/type-params-in-different-spaces-2.rs:10:9
    |
+LL |     fn op(_: T) -> Self;
+   |     -------------------- required by `Tr::op`
+...
 LL |         Tr::op(u)
    |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
    |
    = help: consider adding a `where Self: Tr<U>` bound
-note: required by `Tr::op`
-  --> $DIR/type-params-in-different-spaces-2.rs:5:5
-   |
-LL |     fn op(_: T) -> Self;
-   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
   --> $DIR/type-params-in-different-spaces-2.rs:16:9
    |
+LL |     fn op(_: T) -> Self;
+   |     -------------------- required by `Tr::op`
+...
 LL |         Tr::op(u)
    |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
    |
    = help: consider adding a `where Self: Tr<U>` bound
-note: required by `Tr::op`
-  --> $DIR/type-params-in-different-spaces-2.rs:5:5
-   |
-LL |     fn op(_: T) -> Self;
-   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr
index a31ee83..7fb3731 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr
@@ -3,14 +3,12 @@
    |
 LL |     is_send::<T::AssocType>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `<T as Trait>::AssocType` cannot be sent between threads safely
+...
+LL | fn is_send<T:Send>() {
+   | -------------------- required by `is_send`
    |
    = help: the trait `std::marker::Send` is not implemented for `<T as Trait>::AssocType`
    = help: consider adding a `where <T as Trait>::AssocType: std::marker::Send` bound
-note: required by `is_send`
-  --> $DIR/typeck-default-trait-impl-assoc-type.rs:12:1
-   |
-LL | fn is_send<T:Send>() {
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr
index db1d7d8..8389356 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr
@@ -1,17 +1,15 @@
 error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)`
   --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:16:5
    |
+LL | fn is_mytrait<T: MyTrait>() {}
+   | --------------------------- required by `is_mytrait`
+...
 LL |     is_mytrait::<(MyS2, MyS)>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`
    |
    = help: the following implementations were found:
              <MyS2 as MyTrait>
    = note: required because it appears within the type `(MyS2, MyS)`
-note: required by `is_mytrait`
-  --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:11:1
-   |
-LL | fn is_mytrait<T: MyTrait>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr
index 0f90518..eee186f 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr
@@ -1,16 +1,14 @@
 error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied
   --> $DIR/typeck-default-trait-impl-constituent-types.rs:20:5
    |
+LL | fn is_mytrait<T: MyTrait>() {}
+   | --------------------------- required by `is_mytrait`
+...
 LL |     is_mytrait::<MyS2>();
    |     ^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `MyS2`
    |
    = help: the following implementations were found:
              <MyS2 as MyTrait>
-note: required by `is_mytrait`
-  --> $DIR/typeck-default-trait-impl-constituent-types.rs:15:1
-   |
-LL | fn is_mytrait<T: MyTrait>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr
index 8442f47..1e6adeb 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr
@@ -1,15 +1,13 @@
 error[E0277]: `MyNotSendable` cannot be sent between threads safely
   --> $DIR/typeck-default-trait-impl-negation-send.rs:19:5
    |
+LL | fn is_send<T: Send>() {}
+   | --------------------- required by `is_send`
+...
 LL |     is_send::<MyNotSendable>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ `MyNotSendable` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `MyNotSendable`
-note: required by `is_send`
-  --> $DIR/typeck-default-trait-impl-negation-send.rs:15:1
-   |
-LL | fn is_send<T: Send>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
index 4d435bf..d4f8f5a 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
@@ -1,43 +1,37 @@
 error[E0277]: `MyNotSync` cannot be shared between threads safely
   --> $DIR/typeck-default-trait-impl-negation-sync.rs:33:5
    |
+LL | fn is_sync<T: Sync>() {}
+   | --------------------- required by `is_sync`
+...
 LL |     is_sync::<MyNotSync>();
    |     ^^^^^^^^^^^^^^^^^^^^ `MyNotSync` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `MyNotSync`
-note: required by `is_sync`
-  --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:1
-   |
-LL | fn is_sync<T: Sync>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::cell::UnsafeCell<u8>` cannot be shared between threads safely
   --> $DIR/typeck-default-trait-impl-negation-sync.rs:36:5
    |
+LL | fn is_sync<T: Sync>() {}
+   | --------------------- required by `is_sync`
+...
 LL |     is_sync::<MyTypeWUnsafe>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<u8>` cannot be shared between threads safely
    |
    = help: within `MyTypeWUnsafe`, the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell<u8>`
    = note: required because it appears within the type `MyTypeWUnsafe`
-note: required by `is_sync`
-  --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:1
-   |
-LL | fn is_sync<T: Sync>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `Managed` cannot be shared between threads safely
   --> $DIR/typeck-default-trait-impl-negation-sync.rs:39:5
    |
+LL | fn is_sync<T: Sync>() {}
+   | --------------------- required by `is_sync`
+...
 LL |     is_sync::<MyTypeManaged>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely
    |
    = help: within `MyTypeManaged`, the trait `std::marker::Sync` is not implemented for `Managed`
    = note: required because it appears within the type `MyTypeManaged`
-note: required by `is_sync`
-  --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:1
-   |
-LL | fn is_sync<T: Sync>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr
index 751083d..e993098b 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr
@@ -1,30 +1,26 @@
 error[E0277]: the trait bound `ThisImplsUnsafeTrait: MyTrait` is not satisfied
   --> $DIR/typeck-default-trait-impl-negation.rs:21:5
    |
+LL | fn is_my_trait<T: MyTrait>() {}
+   | ---------------------------- required by `is_my_trait`
+...
 LL |     is_my_trait::<ThisImplsUnsafeTrait>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `ThisImplsUnsafeTrait`
    |
    = help: the following implementations were found:
              <ThisImplsUnsafeTrait as MyTrait>
-note: required by `is_my_trait`
-  --> $DIR/typeck-default-trait-impl-negation.rs:16:1
-   |
-LL | fn is_my_trait<T: MyTrait>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `ThisImplsTrait: MyUnsafeTrait` is not satisfied
   --> $DIR/typeck-default-trait-impl-negation.rs:24:5
    |
+LL | fn is_my_unsafe_trait<T: MyUnsafeTrait>() {}
+   | ----------------------------------------- required by `is_my_unsafe_trait`
+...
 LL |     is_my_unsafe_trait::<ThisImplsTrait>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyUnsafeTrait` is not implemented for `ThisImplsTrait`
    |
    = help: the following implementations were found:
              <ThisImplsTrait as MyUnsafeTrait>
-note: required by `is_my_unsafe_trait`
-  --> $DIR/typeck-default-trait-impl-negation.rs:17:1
-   |
-LL | fn is_my_unsafe_trait<T: MyUnsafeTrait>() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr
index d45cbb2..d87a638 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `u32: Signed` is not satisfied
   --> $DIR/typeck-default-trait-impl-precedence.rs:18:5
    |
+LL | fn is_defaulted<T:Defaulted>() { }
+   | ------------------------------ required by `is_defaulted`
+...
 LL |     is_defaulted::<&'static u32>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
    |
    = note: required because of the requirements on the impl of `Defaulted` for `&'static u32`
-note: required by `is_defaulted`
-  --> $DIR/typeck-default-trait-impl-precedence.rs:11:1
-   |
-LL | fn is_defaulted<T:Defaulted>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr
index a850cc7..5f3a5bc 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr
@@ -3,14 +3,12 @@
    |
 LL |     is_send::<T>()
    |     ^^^^^^^^^^^^ `T` cannot be sent between threads safely
+...
+LL | fn is_send<T:Send>() {
+   | -------------------- required by `is_send`
    |
    = help: the trait `std::marker::Send` is not implemented for `T`
    = help: consider adding a `where T: std::marker::Send` bound
-note: required by `is_send`
-  --> $DIR/typeck-default-trait-impl-send-param.rs:8:1
-   |
-LL | fn is_send<T:Send>() {
-   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.stderr b/src/test/ui/typeck/typeck-unsafe-always-share.stderr
index ff351af..7ed85a1 100644
--- a/src/test/ui/typeck/typeck-unsafe-always-share.stderr
+++ b/src/test/ui/typeck/typeck-unsafe-always-share.stderr
@@ -1,55 +1,47 @@
 error[E0277]: `std::cell::UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
   --> $DIR/typeck-unsafe-always-share.rs:19:5
    |
+LL | fn test<T: Sync>(s: T) {}
+   | ---------------------- required by `test`
+...
 LL |     test(us);
    |     ^^^^ `std::cell::UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell<MySync<{integer}>>`
-note: required by `test`
-  --> $DIR/typeck-unsafe-always-share.rs:15:1
-   |
-LL | fn test<T: Sync>(s: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely
   --> $DIR/typeck-unsafe-always-share.rs:23:5
    |
+LL | fn test<T: Sync>(s: T) {}
+   | ---------------------- required by `test`
+...
 LL |     test(uns);
    |     ^^^^ `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell<NoSync>`
-note: required by `test`
-  --> $DIR/typeck-unsafe-always-share.rs:15:1
-   |
-LL | fn test<T: Sync>(s: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely
   --> $DIR/typeck-unsafe-always-share.rs:27:5
    |
+LL | fn test<T: Sync>(s: T) {}
+   | ---------------------- required by `test`
+...
 LL |     test(ms);
    |     ^^^^ `std::cell::UnsafeCell<NoSync>` cannot be shared between threads safely
    |
    = help: within `MySync<NoSync>`, the trait `std::marker::Sync` is not implemented for `std::cell::UnsafeCell<NoSync>`
    = note: required because it appears within the type `MySync<NoSync>`
-note: required by `test`
-  --> $DIR/typeck-unsafe-always-share.rs:15:1
-   |
-LL | fn test<T: Sync>(s: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `NoSync` cannot be shared between threads safely
   --> $DIR/typeck-unsafe-always-share.rs:30:5
    |
+LL | fn test<T: Sync>(s: T) {}
+   | ---------------------- required by `test`
+...
 LL |     test(NoSync);
    |     ^^^^ `NoSync` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `NoSync`
-note: required by `test`
-  --> $DIR/typeck-unsafe-always-share.rs:15:1
-   |
-LL | fn test<T: Sync>(s: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs
index c6ff94a..bdb8e19 100644
--- a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs
+++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs
@@ -6,7 +6,7 @@
 
 impl Foo {
     fn foo(self: isize, x: isize) -> isize {
-        //~^ ERROR invalid method receiver type
+        //~^ ERROR invalid `self` parameter type
         self.f + x
     }
 }
@@ -17,11 +17,11 @@
 
 impl<T> Bar<T> {
     fn foo(self: Bar<isize>, x: isize) -> isize {
-        //~^ ERROR invalid method receiver type
+        //~^ ERROR invalid `self` parameter type
         x
     }
     fn bar(self: &Bar<usize>, x: isize) -> isize {
-        //~^ ERROR invalid method receiver type
+        //~^ ERROR invalid `self` parameter type
         x
     }
 }
@@ -34,14 +34,14 @@
 
 impl<'a, T> SomeTrait for &'a Bar<T> {
     fn dummy1(self: &&'a Bar<T>) { }
-    fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched method receiver
-    //~^ ERROR mismatched method receiver
+    fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched `self` parameter type
+    //~^ ERROR mismatched `self` parameter type
     fn dummy3(self: &&Bar<T>) {}
-    //~^ ERROR mismatched method receiver
+    //~^ ERROR mismatched `self` parameter type
     //~| expected type `&'a Bar<T>`
     //~| found type `&Bar<T>`
     //~| lifetime mismatch
-    //~| ERROR mismatched method receiver
+    //~| ERROR mismatched `self` parameter type
     //~| expected type `&'a Bar<T>`
     //~| found type `&Bar<T>`
     //~| lifetime mismatch
diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr
index 6da20e3..b2fe1b2 100644
--- a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr
+++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr
@@ -1,31 +1,31 @@
-error[E0307]: invalid method receiver type: isize
+error[E0307]: invalid `self` parameter type: isize
   --> $DIR/ufcs-explicit-self-bad.rs:8:18
    |
 LL |     fn foo(self: isize, x: isize) -> isize {
    |                  ^^^^^
    |
-   = note: type must be `Self` or a type that dereferences to it
+   = note: type of `self` must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0307]: invalid method receiver type: Bar<isize>
+error[E0307]: invalid `self` parameter type: Bar<isize>
   --> $DIR/ufcs-explicit-self-bad.rs:19:18
    |
 LL |     fn foo(self: Bar<isize>, x: isize) -> isize {
    |                  ^^^^^^^^^^
    |
-   = note: type must be `Self` or a type that dereferences to it
+   = note: type of `self` must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0307]: invalid method receiver type: &Bar<usize>
+error[E0307]: invalid `self` parameter type: &Bar<usize>
   --> $DIR/ufcs-explicit-self-bad.rs:23:18
    |
 LL |     fn bar(self: &Bar<usize>, x: isize) -> isize {
    |                  ^^^^^^^^^^^
    |
-   = note: type must be `Self` or a type that dereferences to it
+   = note: type of `self` must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/ufcs-explicit-self-bad.rs:37:21
    |
 LL |     fn dummy2(self: &Bar<T>) {}
@@ -44,7 +44,7 @@
 LL | impl<'a, T> SomeTrait for &'a Bar<T> {
    |      ^^
 
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/ufcs-explicit-self-bad.rs:37:21
    |
 LL |     fn dummy2(self: &Bar<T>) {}
@@ -63,7 +63,7 @@
 LL |     fn dummy2(self: &Bar<T>) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/ufcs-explicit-self-bad.rs:39:21
    |
 LL |     fn dummy3(self: &&Bar<T>) {}
@@ -82,7 +82,7 @@
 LL | impl<'a, T> SomeTrait for &'a Bar<T> {
    |      ^^
 
-error[E0308]: mismatched method receiver
+error[E0308]: mismatched `self` parameter type
   --> $DIR/ufcs-explicit-self-bad.rs:39:21
    |
 LL |     fn dummy3(self: &&Bar<T>) {}
@@ -103,4 +103,5 @@
 
 error: aborting due to 7 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0307, E0308.
+For more information about an error, try `rustc --explain E0307`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr
index fd5ef4b9..dd024b7 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq<dyn Foo<(isize,), Output = ()>>` is not satisfied
   --> $DIR/unboxed-closure-sugar-default.rs:21:5
    |
+LL | fn eq<A: ?Sized,B: ?Sized>() where A : Eq<B> { }
+   | -------------------------------------------- required by `eq`
+...
 LL |     eq::<dyn Foo<(isize,), isize, Output=()>, dyn Foo(isize)>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output = ()>>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>`
-   |
-note: required by `eq`
-  --> $DIR/unboxed-closure-sugar-default.rs:14:1
-   |
-LL | fn eq<A: ?Sized,B: ?Sized>() where A : Eq<B> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr
index 005a86b..83754bd 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr
@@ -1,15 +1,12 @@
 error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq<dyn Foo<(), Output = ()>>` is not satisfied
   --> $DIR/unboxed-closure-sugar-equiv.rs:43:5
    |
+LL |   fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
+   |   ----------------------------------- required by `eq`
+...
 LL | /     eq::< dyn Foo<(),Output=()>,
 LL | |           dyn Foo(char)                                               >();
    | |_______________________________________________________________________^ the trait `Eq<dyn Foo<(), Output = ()>>` is not implemented for `dyn Foo<(char,), Output = ()>`
-   |
-note: required by `eq`
-  --> $DIR/unboxed-closure-sugar-equiv.rs:16:1
-   |
-LL | fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
index fcf11290..d64e54a 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
@@ -1,15 +1,13 @@
 error[E0277]: expected a `std::ops::Fn<(isize,)>` closure, found `S`
   --> $DIR/unboxed-closures-fnmut-as-fn.rs:28:13
    |
+LL | fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
+   | -------------------------------------------------------- required by `call_it`
+...
 LL |     let x = call_it(&S, 22);
    |             ^^^^^^^ expected an `Fn<(isize,)>` closure, found `S`
    |
    = help: the trait `std::ops::Fn<(isize,)>` is not implemented for `S`
-note: required by `call_it`
-  --> $DIR/unboxed-closures-fnmut-as-fn.rs:23:1
-   |
-LL | fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
index 2e18458..18276d5 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
@@ -2,7 +2,7 @@
   --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
    |
 LL |     mut_.call((0, ));
-   |          ^^^^
+   |          ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:31]`
    |
    = note: mut_ is a function, perhaps you wish to call it
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
index ca02982..3d20b5d 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
@@ -1,67 +1,57 @@
 error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13
    |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | --------------------------------------------------------- required by `call_it`
+...
 LL |     let x = call_it(&square, 22);
    |             ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
    |
    = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
-note: required by `call_it`
-  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1
-   |
-LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13
    |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | --------------------------------------------------------- required by `call_it`
+...
 LL |     let x = call_it(&square, 22);
    |             ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
    |
    = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
-note: required by `call_it`
-  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1
-   |
-LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13
    |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | -------------------------------------------------------------------- required by `call_it_mut`
+...
 LL |     let y = call_it_mut(&mut square, 22);
    |             ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
    |
    = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
-note: required by `call_it_mut`
-  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1
-   |
-LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13
    |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | -------------------------------------------------------------------- required by `call_it_mut`
+...
 LL |     let y = call_it_mut(&mut square, 22);
    |             ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
    |
    = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
-note: required by `call_it_mut`
-  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1
-   |
-LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:13
    |
+LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
+   | ----------------------------------------------------------------- required by `call_it_once`
+...
 LL |     let z = call_it_once(square, 22);
    |             ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
    |
    = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
-note: required by `call_it_once`
-  --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:1
-   |
-LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
index 0abc58a..f435a05 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
@@ -1,67 +1,57 @@
 error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-abi.rs:12:13
    |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | --------------------------------------------------------- required by `call_it`
+...
 LL |     let x = call_it(&square, 22);
    |             ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
    |
    = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
-note: required by `call_it`
-  --> $DIR/unboxed-closures-wrong-abi.rs:7:1
-   |
-LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-abi.rs:12:13
    |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | --------------------------------------------------------- required by `call_it`
+...
 LL |     let x = call_it(&square, 22);
    |             ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
    |
    = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
-note: required by `call_it`
-  --> $DIR/unboxed-closures-wrong-abi.rs:7:1
-   |
-LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-abi.rs:18:13
    |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | -------------------------------------------------------------------- required by `call_it_mut`
+...
 LL |     let y = call_it_mut(&mut square, 22);
    |             ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
    |
    = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
-note: required by `call_it_mut`
-  --> $DIR/unboxed-closures-wrong-abi.rs:8:1
-   |
-LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-abi.rs:18:13
    |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | -------------------------------------------------------------------- required by `call_it_mut`
+...
 LL |     let y = call_it_mut(&mut square, 22);
    |             ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
    |
    = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
-note: required by `call_it_mut`
-  --> $DIR/unboxed-closures-wrong-abi.rs:8:1
-   |
-LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-abi.rs:24:13
    |
+LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
+   | ----------------------------------------------------------------- required by `call_it_once`
+...
 LL |     let z = call_it_once(square, 22);
    |             ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
    |
    = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
-note: required by `call_it_once`
-  --> $DIR/unboxed-closures-wrong-abi.rs:9:1
-   |
-LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
index 19b87ad..efdb2e8 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
@@ -1,67 +1,57 @@
 error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13
    |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | --------------------------------------------------------- required by `call_it`
+...
 LL |     let x = call_it(&square, 22);
    |             ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
    |
    = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
-note: required by `call_it`
-  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1
-   |
-LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13
    |
+LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
+   | --------------------------------------------------------- required by `call_it`
+...
 LL |     let x = call_it(&square, 22);
    |             ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
    |
    = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
-note: required by `call_it`
-  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1
-   |
-LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13
    |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | -------------------------------------------------------------------- required by `call_it_mut`
+...
 LL |     let y = call_it_mut(&mut square, 22);
    |             ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
    |
    = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
-note: required by `call_it_mut`
-  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1
-   |
-LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13
    |
+LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
+   | -------------------------------------------------------------------- required by `call_it_mut`
+...
 LL |     let y = call_it_mut(&mut square, 22);
    |             ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
    |
    = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
-note: required by `call_it_mut`
-  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1
-   |
-LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:13
    |
+LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
+   | ----------------------------------------------------------------- required by `call_it_once`
+...
 LL |     let z = call_it_once(square, 22);
    |             ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
    |
    = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
-note: required by `call_it_once`
-  --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:1
-   |
-LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs b/src/test/ui/underscore-imports/auxiliary/duplicate.rs
similarity index 100%
rename from src/test/ui/rfc-2166-underscore-imports/auxiliary/duplicate.rs
rename to src/test/ui/underscore-imports/auxiliary/duplicate.rs
diff --git a/src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs b/src/test/ui/underscore-imports/auxiliary/underscore-imports.rs
similarity index 100%
rename from src/test/ui/rfc-2166-underscore-imports/auxiliary/underscore-imports.rs
rename to src/test/ui/underscore-imports/auxiliary/underscore-imports.rs
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/underscore-imports/basic.rs
similarity index 100%
rename from src/test/ui/rfc-2166-underscore-imports/basic.rs
rename to src/test/ui/underscore-imports/basic.rs
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/underscore-imports/basic.stderr
similarity index 100%
rename from src/test/ui/rfc-2166-underscore-imports/basic.stderr
rename to src/test/ui/underscore-imports/basic.stderr
diff --git a/src/test/ui/underscore-imports/cycle.rs b/src/test/ui/underscore-imports/cycle.rs
new file mode 100644
index 0000000..bacf9b2
--- /dev/null
+++ b/src/test/ui/underscore-imports/cycle.rs
@@ -0,0 +1,18 @@
+// Check that cyclic glob imports are allowed with underscore imports
+
+// check-pass
+
+mod x {
+    pub use crate::y::*;
+    pub use std::ops::Deref as _;
+}
+
+mod y {
+    pub use crate::x::*;
+    pub use std::ops::Deref as _;
+}
+
+pub fn main() {
+    use x::*;
+    (&0).deref();
+}
diff --git a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs b/src/test/ui/underscore-imports/duplicate.rs
similarity index 100%
rename from src/test/ui/rfc-2166-underscore-imports/duplicate.rs
rename to src/test/ui/underscore-imports/duplicate.rs
diff --git a/src/test/ui/rfc-2166-underscore-imports/intercrate.rs b/src/test/ui/underscore-imports/intercrate.rs
similarity index 100%
rename from src/test/ui/rfc-2166-underscore-imports/intercrate.rs
rename to src/test/ui/underscore-imports/intercrate.rs
diff --git a/src/test/ui/underscore-imports/shadow.rs b/src/test/ui/underscore-imports/shadow.rs
new file mode 100644
index 0000000..325f200
--- /dev/null
+++ b/src/test/ui/underscore-imports/shadow.rs
@@ -0,0 +1,23 @@
+// Check that underscore imports don't cause glob imports to be unshadowed
+
+mod a {
+    pub use std::ops::Deref as Shadow;
+}
+
+mod b {
+    pub use crate::a::*;
+    macro_rules! m {
+        ($i:ident) => { pub struct $i; }
+    }
+    m!(Shadow);
+}
+
+mod c {
+    use crate::b::Shadow as _; // Only imports the struct
+
+    fn f(x: &()) {
+        x.deref(); //~ ERROR no method named `deref` found
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/underscore-imports/shadow.stderr b/src/test/ui/underscore-imports/shadow.stderr
new file mode 100644
index 0000000..63262d0
--- /dev/null
+++ b/src/test/ui/underscore-imports/shadow.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no method named `deref` found for type `&()` in the current scope
+  --> $DIR/shadow.rs:19:11
+   |
+LL |         x.deref();
+   |           ^^^^^ method not found in `&()`
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           `use std::ops::Deref;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.rs b/src/test/ui/underscore-imports/unused-2018.rs
similarity index 100%
rename from src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
rename to src/test/ui/underscore-imports/unused-2018.rs
diff --git a/src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr b/src/test/ui/underscore-imports/unused-2018.stderr
similarity index 100%
rename from src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
rename to src/test/ui/underscore-imports/unused-2018.stderr
diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr
index be6ed8d..2079f6f 100644
--- a/src/test/ui/unevaluated_fixed_size_array_len.stderr
+++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr
@@ -1,16 +1,14 @@
 error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied
   --> $DIR/unevaluated_fixed_size_array_len.rs:12:5
    |
+LL |     fn foo();
+   |     --------- required by `Foo::foo`
+...
 LL |     <[(); 0] as Foo>::foo()
    |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]`
    |
    = help: the following implementations were found:
              <[(); 1] as Foo>
-note: required by `Foo::foo`
-  --> $DIR/unevaluated_fixed_size_array_len.rs:4:5
-   |
-LL |     fn foo();
-   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
index 45976f8..29ff1dc 100644
--- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -3,6 +3,7 @@
    |
 LL | / enum Foo {
 LL | |     A(foo::SecretlyEmpty),
+   | |     - not covered
 LL | |     B(foo::NotSoSecretlyEmpty),
 LL | |     C(NotSoSecretlyEmpty),
 LL | |     D(u32),
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
index 37a0093..4f4c779 100644
--- a/src/test/ui/union/union-derive-clone.stderr
+++ b/src/test/ui/union/union-derive-clone.stderr
@@ -13,7 +13,7 @@
    | ----------- method `clone` not found for this
 ...
 LL |     let w = u.clone();
-   |               ^^^^^
+   |               ^^^^^ method not found in `U4<CloneNoCopy>`
    |
    = note: the method `clone` exists but the following trait bounds were not satisfied:
            `U4<CloneNoCopy> : std::clone::Clone`
diff --git a/src/test/ui/union/union-generic.stderr b/src/test/ui/union/union-generic.stderr
index 6a3216d..f13b2de 100644
--- a/src/test/ui/union/union-generic.stderr
+++ b/src/test/ui/union/union-generic.stderr
@@ -1,26 +1,20 @@
 error[E0277]: the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied
   --> $DIR/union-generic.rs:8:13
    |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
 LL |     let u = U { a: Rc::new(0u32) };
    |             ^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc<u32>`
-   |
-note: required by `U`
-  --> $DIR/union-generic.rs:3:1
-   |
-LL | union U<T: Copy> {
-   | ^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied
   --> $DIR/union-generic.rs:10:13
    |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
 LL |     let u = U::<Rc<u32>> { a: Default::default() };
    |             ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::rc::Rc<u32>`
-   |
-note: required by `U`
-  --> $DIR/union-generic.rs:3:1
-   |
-LL | union U<T: Copy> {
-   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/union/union-repr-c.rs b/src/test/ui/union/union-repr-c.rs
index 658452d..1367835 100644
--- a/src/test/ui/union/union-repr-c.rs
+++ b/src/test/ui/union/union-repr-c.rs
@@ -12,7 +12,7 @@
 
 extern "C" {
     static FOREIGN1: U; // OK
-    static FOREIGN2: W; //~ ERROR union has unspecified layout
+    static FOREIGN2: W; //~ ERROR `extern` block uses type `W`
 }
 
 fn main() {}
diff --git a/src/test/ui/union/union-repr-c.stderr b/src/test/ui/union/union-repr-c.stderr
index c60817a..c8bc038 100644
--- a/src/test/ui/union/union-repr-c.stderr
+++ b/src/test/ui/union/union-repr-c.stderr
@@ -1,8 +1,8 @@
-error: `extern` block uses type `W` which is not FFI-safe: this union has unspecified layout
+error: `extern` block uses type `W`, which is not FFI-safe
   --> $DIR/union-repr-c.rs:15:22
    |
 LL |     static FOREIGN2: W;
-   |                      ^
+   |                      ^ not FFI-safe
    |
 note: lint level defined here
   --> $DIR/union-repr-c.rs:2:9
@@ -10,6 +10,7 @@
 LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
+   = note: this union has unspecified layout
 note: type defined here
   --> $DIR/union-repr-c.rs:9:1
    |
diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr
index 407905f..cd46878 100644
--- a/src/test/ui/unique-object-noncopyable.stderr
+++ b/src/test/ui/unique-object-noncopyable.stderr
@@ -2,7 +2,7 @@
   --> $DIR/unique-object-noncopyable.rs:24:16
    |
 LL |     let _z = y.clone();
-   |                ^^^^^
+   |                ^^^^^ method not found in `std::boxed::Box<dyn Foo>`
    |
    = note: the method `clone` exists but the following trait bounds were not satisfied:
            `std::boxed::Box<dyn Foo> : std::clone::Clone`
diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr
index 0f6ba90..19ef2b2 100644
--- a/src/test/ui/unique-pinned-nocopy.stderr
+++ b/src/test/ui/unique-pinned-nocopy.stderr
@@ -2,7 +2,7 @@
   --> $DIR/unique-pinned-nocopy.rs:12:16
    |
 LL |     let _j = i.clone();
-   |                ^^^^^
+   |                ^^^^^ method not found in `std::boxed::Box<R>`
    |
    = note: the method `clone` exists but the following trait bounds were not satisfied:
            `std::boxed::Box<R> : std::clone::Clone`
diff --git a/src/test/ui/unreachable/unreachable-in-call.rs b/src/test/ui/unreachable/unreachable-in-call.rs
index 25f849d..dd94e79 100644
--- a/src/test/ui/unreachable/unreachable-in-call.rs
+++ b/src/test/ui/unreachable/unreachable-in-call.rs
@@ -14,7 +14,7 @@
          get_u8()); //~ ERROR unreachable expression
 }
 fn diverge_second() {
-    call( //~ ERROR unreachable expression
+    call( //~ ERROR unreachable call
         get_u8(),
         diverge());
 }
diff --git a/src/test/ui/unreachable/unreachable-in-call.stderr b/src/test/ui/unreachable/unreachable-in-call.stderr
index f8dd545..c740011 100644
--- a/src/test/ui/unreachable/unreachable-in-call.stderr
+++ b/src/test/ui/unreachable/unreachable-in-call.stderr
@@ -10,13 +10,11 @@
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: unreachable expression
+error: unreachable call
   --> $DIR/unreachable-in-call.rs:17:5
    |
-LL | /     call(
-LL | |         get_u8(),
-LL | |         diverge());
-   | |__________________^
+LL |     call(
+   |     ^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/unsized/unsized-bare-typaram.stderr b/src/test/ui/unsized/unsized-bare-typaram.stderr
index cee1459..c39c648 100644
--- a/src/test/ui/unsized/unsized-bare-typaram.stderr
+++ b/src/test/ui/unsized/unsized-bare-typaram.stderr
@@ -1,17 +1,14 @@
 error[E0277]: the size for values of type `T` cannot be known at compilation time
   --> $DIR/unsized-bare-typaram.rs:2:23
    |
+LL | fn bar<T: Sized>() { }
+   | ------------------ required by `bar`
 LL | fn foo<T: ?Sized>() { bar::<T>() }
    |                       ^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `T`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where T: std::marker::Sized` bound
-note: required by `bar`
-  --> $DIR/unsized-bare-typaram.rs:1:1
-   |
-LL | fn bar<T: Sized>() { }
-   | ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsized/unsized-enum.stderr b/src/test/ui/unsized/unsized-enum.stderr
index 20857a1..dff9348 100644
--- a/src/test/ui/unsized/unsized-enum.stderr
+++ b/src/test/ui/unsized/unsized-enum.stderr
@@ -1,17 +1,15 @@
 error[E0277]: the size for values of type `T` cannot be known at compilation time
   --> $DIR/unsized-enum.rs:6:36
    |
+LL | enum Foo<U> { FooSome(U), FooNone }
+   | ----------- required by `Foo`
+LL | fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
 LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
    |                                    ^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `T`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where T: std::marker::Sized` bound
-note: required by `Foo`
-  --> $DIR/unsized-enum.rs:4:1
-   |
-LL | enum Foo<U> { FooSome(U), FooNone }
-   | ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr
index 98eecab..1a726bb 100644
--- a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr
+++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr
@@ -1,17 +1,15 @@
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized-inherent-impl-self-type.rs:7:17
    |
+LL | struct S5<Y>(Y);
+   | ---------------- required by `S5`
+LL | 
 LL | impl<X: ?Sized> S5<X> {
    |                 ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `X`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where X: std::marker::Sized` bound
-note: required by `S5`
-  --> $DIR/unsized-inherent-impl-self-type.rs:5:1
-   |
-LL | struct S5<Y>(Y);
-   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr
index 7add65c..7951151 100644
--- a/src/test/ui/unsized/unsized-struct.stderr
+++ b/src/test/ui/unsized/unsized-struct.stderr
@@ -1,21 +1,22 @@
 error[E0277]: the size for values of type `T` cannot be known at compilation time
   --> $DIR/unsized-struct.rs:6:36
    |
+LL | struct Foo<T> { data: T }
+   | ------------- required by `Foo`
+LL | fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
 LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
    |                                    ^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `T`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where T: std::marker::Sized` bound
-note: required by `Foo`
-  --> $DIR/unsized-struct.rs:4:1
-   |
-LL | struct Foo<T> { data: T }
-   | ^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
   --> $DIR/unsized-struct.rs:13:24
    |
+LL | fn is_sized<T:Sized>() { }
+   | ---------------------- required by `is_sized`
+...
 LL | fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
    |                        ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
@@ -23,11 +24,6 @@
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where T: std::marker::Sized` bound
    = note: required because it appears within the type `Bar<T>`
-note: required by `is_sized`
-  --> $DIR/unsized-struct.rs:1:1
-   |
-LL | fn is_sized<T:Sized>() { }
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr
index c39f365..f399f8d 100644
--- a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr
+++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr
@@ -1,17 +1,15 @@
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized-trait-impl-self-type.rs:10:17
    |
+LL | struct S5<Y>(Y);
+   | ---------------- required by `S5`
+LL | 
 LL | impl<X: ?Sized> T3<X> for S5<X> {
    |                 ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `X`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where X: std::marker::Sized` bound
-note: required by `S5`
-  --> $DIR/unsized-trait-impl-self-type.rs:8:1
-   |
-LL | struct S5<Y>(Y);
-   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized3.stderr
index 2c7b86c..9064aa1 100644
--- a/src/test/ui/unsized3.stderr
+++ b/src/test/ui/unsized3.stderr
@@ -3,34 +3,33 @@
    |
 LL |     f2::<X>(x);
    |     ^^^^^^^ doesn't have a size known at compile-time
+...
+LL | fn f2<X>(x: &X) {
+   | --------------- required by `f2`
    |
    = help: the trait `std::marker::Sized` is not implemented for `X`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where X: std::marker::Sized` bound
-note: required by `f2`
-  --> $DIR/unsized3.rs:10:1
-   |
-LL | fn f2<X>(x: &X) {
-   | ^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized3.rs:18:5
    |
 LL |     f4::<X>(x);
    |     ^^^^^^^ doesn't have a size known at compile-time
+...
+LL | fn f4<X: T>(x: &X) {
+   | ------------------ required by `f4`
    |
    = help: the trait `std::marker::Sized` is not implemented for `X`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where X: std::marker::Sized` bound
-note: required by `f4`
-  --> $DIR/unsized3.rs:21:1
-   |
-LL | fn f4<X: T>(x: &X) {
-   | ^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized3.rs:33:5
    |
+LL | fn f5<Y>(x: &Y) {}
+   | --------------- required by `f5`
+...
 LL |     f5(x1);
    |     ^^ doesn't have a size known at compile-time
    |
@@ -38,11 +37,6 @@
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where X: std::marker::Sized` bound
    = note: required because it appears within the type `S<X>`
-note: required by `f5`
-  --> $DIR/unsized3.rs:24:1
-   |
-LL | fn f5<Y>(x: &Y) {}
-   | ^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized3.rs:40:5
@@ -72,6 +66,9 @@
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized3.rs:45:5
    |
+LL | fn f5<Y>(x: &Y) {}
+   | --------------- required by `f5`
+...
 LL |     f5(&(32, *x1));
    |     ^^ doesn't have a size known at compile-time
    |
@@ -80,11 +77,6 @@
    = help: consider adding a `where X: std::marker::Sized` bound
    = note: required because it appears within the type `S<X>`
    = note: required because it appears within the type `({integer}, S<X>)`
-note: required by `f5`
-  --> $DIR/unsized3.rs:24:1
-   |
-LL | fn f5<Y>(x: &Y) {}
-   | ^^^^^^^^^^^^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/wf/wf-const-type.stderr b/src/test/ui/wf/wf-const-type.stderr
index 4df4292..531aadc 100644
--- a/src/test/ui/wf/wf-const-type.stderr
+++ b/src/test/ui/wf/wf-const-type.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `NotCopy: std::marker::Copy` is not satisfied
   --> $DIR/wf-const-type.rs:10:12
    |
+LL | struct IsCopy<T:Copy> { t: T }
+   | --------------------- required by `IsCopy`
+...
 LL | const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
    |            ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `NotCopy`
    |
    = note: required because of the requirements on the impl of `std::marker::Copy` for `std::option::Option<NotCopy>`
-note: required by `IsCopy`
-  --> $DIR/wf-const-type.rs:7:1
-   |
-LL | struct IsCopy<T:Copy> { t: T }
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-enum-bound.stderr b/src/test/ui/wf/wf-enum-bound.stderr
index de28a88..d5632f4 100644
--- a/src/test/ui/wf/wf-enum-bound.stderr
+++ b/src/test/ui/wf/wf-enum-bound.stderr
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
   --> $DIR/wf-enum-bound.rs:9:1
    |
+LL |   trait ExtraCopy<T:Copy> { }
+   |   ----------------------- required by `ExtraCopy`
+LL | 
 LL | / enum SomeEnum<T,U>
 LL | |     where T: ExtraCopy<U>
 LL | | {
@@ -9,11 +12,6 @@
    | |_^ the trait `std::marker::Copy` is not implemented for `U`
    |
    = help: consider adding a `where U: std::marker::Copy` bound
-note: required by `ExtraCopy`
-  --> $DIR/wf-enum-bound.rs:7:1
-   |
-LL | trait ExtraCopy<T:Copy> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr
index 6c1267c..51ee23f 100644
--- a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr
+++ b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied
   --> $DIR/wf-enum-fields-struct-variant.rs:13:9
    |
+LL | struct IsCopy<T:Copy> {
+   | --------------------- required by `IsCopy`
+...
 LL |         f: IsCopy<A>
    |         ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A`
    |
    = help: consider adding a `where A: std::marker::Copy` bound
-note: required by `IsCopy`
-  --> $DIR/wf-enum-fields-struct-variant.rs:7:1
-   |
-LL | struct IsCopy<T:Copy> {
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-enum-fields.stderr b/src/test/ui/wf/wf-enum-fields.stderr
index 9c4eec6..5f4e7c6 100644
--- a/src/test/ui/wf/wf-enum-fields.stderr
+++ b/src/test/ui/wf/wf-enum-fields.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied
   --> $DIR/wf-enum-fields.rs:12:17
    |
+LL | struct IsCopy<T:Copy> {
+   | --------------------- required by `IsCopy`
+...
 LL |     SomeVariant(IsCopy<A>)
    |                 ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A`
    |
    = help: consider adding a `where A: std::marker::Copy` bound
-note: required by `IsCopy`
-  --> $DIR/wf-enum-fields.rs:7:1
-   |
-LL | struct IsCopy<T:Copy> {
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-fn-where-clause.stderr b/src/test/ui/wf/wf-fn-where-clause.stderr
index b50e895..4bc2e37 100644
--- a/src/test/ui/wf/wf-fn-where-clause.stderr
+++ b/src/test/ui/wf/wf-fn-where-clause.stderr
@@ -1,17 +1,15 @@
 error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
   --> $DIR/wf-fn-where-clause.rs:8:1
    |
+LL |   trait ExtraCopy<T:Copy> { }
+   |   ----------------------- required by `ExtraCopy`
+LL | 
 LL | / fn foo<T,U>() where T: ExtraCopy<U>
 LL | | {
 LL | | }
    | |_^ the trait `std::marker::Copy` is not implemented for `U`
    |
    = help: consider adding a `where U: std::marker::Copy` bound
-note: required by `ExtraCopy`
-  --> $DIR/wf-fn-where-clause.rs:6:1
-   |
-LL | trait ExtraCopy<T:Copy> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `(dyn std::marker::Copy + 'static)` cannot be known at compilation time
   --> $DIR/wf-fn-where-clause.rs:12:1
diff --git a/src/test/ui/wf/wf-impl-associated-type-trait.stderr b/src/test/ui/wf/wf-impl-associated-type-trait.stderr
index 158b55a..ceafb4f 100644
--- a/src/test/ui/wf/wf-impl-associated-type-trait.stderr
+++ b/src/test/ui/wf/wf-impl-associated-type-trait.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `T: MyHash` is not satisfied
   --> $DIR/wf-impl-associated-type-trait.rs:17:5
    |
+LL | pub struct MySet<T:MyHash> {
+   | -------------------------- required by `MySet`
+...
 LL |     type Bar = MySet<T>;
    |     ^^^^^^^^^^^^^^^^^^^^ the trait `MyHash` is not implemented for `T`
    |
    = help: consider adding a `where T: MyHash` bound
-note: required by `MySet`
-  --> $DIR/wf-impl-associated-type-trait.rs:8:1
-   |
-LL | pub struct MySet<T:MyHash> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-in-fn-arg.stderr b/src/test/ui/wf/wf-in-fn-arg.stderr
index 8635dad..e7432f8 100644
--- a/src/test/ui/wf/wf-in-fn-arg.stderr
+++ b/src/test/ui/wf/wf-in-fn-arg.stderr
@@ -1,17 +1,15 @@
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/wf-in-fn-arg.rs:10:1
    |
+LL |   struct MustBeCopy<T:Copy> {
+   |   ------------------------- required by `MustBeCopy`
+...
 LL | / fn bar<T>(_: &MustBeCopy<T>)
 LL | | {
 LL | | }
    | |_^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `MustBeCopy`
-  --> $DIR/wf-in-fn-arg.rs:6:1
-   |
-LL | struct MustBeCopy<T:Copy> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-in-fn-ret.stderr b/src/test/ui/wf/wf-in-fn-ret.stderr
index 3879f7b..005ffe8 100644
--- a/src/test/ui/wf/wf-in-fn-ret.stderr
+++ b/src/test/ui/wf/wf-in-fn-ret.stderr
@@ -1,17 +1,15 @@
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/wf-in-fn-ret.rs:10:1
    |
+LL |   struct MustBeCopy<T:Copy> {
+   |   ------------------------- required by `MustBeCopy`
+...
 LL | / fn bar<T>() -> MustBeCopy<T>
 LL | | {
 LL | | }
    | |_^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `MustBeCopy`
-  --> $DIR/wf-in-fn-ret.rs:6:1
-   |
-LL | struct MustBeCopy<T:Copy> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-in-fn-type-arg.stderr b/src/test/ui/wf/wf-in-fn-type-arg.stderr
index 40cb4a7..b4cd921 100644
--- a/src/test/ui/wf/wf-in-fn-type-arg.stderr
+++ b/src/test/ui/wf/wf-in-fn-type-arg.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/wf-in-fn-type-arg.rs:9:5
    |
+LL | struct MustBeCopy<T:Copy> {
+   | ------------------------- required by `MustBeCopy`
+...
 LL |     x: fn(MustBeCopy<T>)
    |     ^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `MustBeCopy`
-  --> $DIR/wf-in-fn-type-arg.rs:3:1
-   |
-LL | struct MustBeCopy<T:Copy> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-in-fn-type-ret.stderr b/src/test/ui/wf/wf-in-fn-type-ret.stderr
index 059f164..988fbed 100644
--- a/src/test/ui/wf/wf-in-fn-type-ret.stderr
+++ b/src/test/ui/wf/wf-in-fn-type-ret.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/wf-in-fn-type-ret.rs:9:5
    |
+LL | struct MustBeCopy<T:Copy> {
+   | ------------------------- required by `MustBeCopy`
+...
 LL |     x: fn() -> MustBeCopy<T>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `MustBeCopy`
-  --> $DIR/wf-in-fn-type-ret.rs:3:1
-   |
-LL | struct MustBeCopy<T:Copy> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-in-fn-where-clause.stderr b/src/test/ui/wf/wf-in-fn-where-clause.stderr
index 1e732a3..0af38dd 100644
--- a/src/test/ui/wf/wf-in-fn-where-clause.stderr
+++ b/src/test/ui/wf/wf-in-fn-where-clause.stderr
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
   --> $DIR/wf-in-fn-where-clause.rs:9:1
    |
+LL |   trait MustBeCopy<T:Copy> {
+   |   ------------------------ required by `MustBeCopy`
+...
 LL | / fn bar<T,U>()
 LL | |     where T: MustBeCopy<U>
 LL | | {
@@ -8,11 +11,6 @@
    | |_^ the trait `std::marker::Copy` is not implemented for `U`
    |
    = help: consider adding a `where U: std::marker::Copy` bound
-note: required by `MustBeCopy`
-  --> $DIR/wf-in-fn-where-clause.rs:6:1
-   |
-LL | trait MustBeCopy<T:Copy> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-in-obj-type-trait.stderr b/src/test/ui/wf/wf-in-obj-type-trait.stderr
index 2c85dd0..0f4b4e4 100644
--- a/src/test/ui/wf/wf-in-obj-type-trait.stderr
+++ b/src/test/ui/wf/wf-in-obj-type-trait.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/wf-in-obj-type-trait.rs:11:5
    |
+LL | struct MustBeCopy<T:Copy> {
+   | ------------------------- required by `MustBeCopy`
+...
 LL |     x: dyn Object<MustBeCopy<T>>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `MustBeCopy`
-  --> $DIR/wf-in-obj-type-trait.rs:5:1
-   |
-LL | struct MustBeCopy<T:Copy> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr
index b79093f..1e25886 100644
--- a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr
+++ b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr
@@ -1,16 +1,14 @@
 error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
   --> $DIR/wf-inherent-impl-method-where-clause.rs:12:5
    |
+LL |   trait ExtraCopy<T:Copy> { }
+   |   ----------------------- required by `ExtraCopy`
+...
 LL | /     fn foo(self) where T: ExtraCopy<U>
 LL | |     {}
    | |______^ the trait `std::marker::Copy` is not implemented for `U`
    |
    = help: consider adding a `where U: std::marker::Copy` bound
-note: required by `ExtraCopy`
-  --> $DIR/wf-inherent-impl-method-where-clause.rs:7:1
-   |
-LL | trait ExtraCopy<T:Copy> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr
index f10ff84..4c389b3 100644
--- a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr
+++ b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr
@@ -1,17 +1,15 @@
 error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
   --> $DIR/wf-inherent-impl-where-clause.rs:11:1
    |
+LL |   trait ExtraCopy<T:Copy> { }
+   |   ----------------------- required by `ExtraCopy`
+...
 LL | / impl<T,U> Foo<T,U> where T: ExtraCopy<U>
 LL | | {
 LL | | }
    | |_^ the trait `std::marker::Copy` is not implemented for `U`
    |
    = help: consider adding a `where U: std::marker::Copy` bound
-note: required by `ExtraCopy`
-  --> $DIR/wf-inherent-impl-where-clause.rs:7:1
-   |
-LL | trait ExtraCopy<T:Copy> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr
index 3b264ec..0d8441f 100644
--- a/src/test/ui/wf/wf-object-safe.stderr
+++ b/src/test/ui/wf/wf-object-safe.stderr
@@ -1,10 +1,11 @@
 error[E0038]: the trait `A` cannot be made into an object
   --> $DIR/wf-object-safe.rs:9:13
    |
+LL |     fn foo(&self, _x: &Self);
+   |        --- method `foo` references the `Self` type in its parameters or return type
+...
 LL |     let _x: &dyn A;
    |             ^^^^^^ the trait `A` cannot be made into an object
-   |
-   = note: method `foo` references the `Self` type in its arguments or return type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-static-type.stderr b/src/test/ui/wf/wf-static-type.stderr
index 4234c71..05a628d 100644
--- a/src/test/ui/wf/wf-static-type.stderr
+++ b/src/test/ui/wf/wf-static-type.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `NotCopy: std::marker::Copy` is not satisfied
   --> $DIR/wf-static-type.rs:10:13
    |
+LL | struct IsCopy<T:Copy> { t: T }
+   | --------------------- required by `IsCopy`
+...
 LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
    |             ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `NotCopy`
    |
    = note: required because of the requirements on the impl of `std::marker::Copy` for `std::option::Option<NotCopy>`
-note: required by `IsCopy`
-  --> $DIR/wf-static-type.rs:7:1
-   |
-LL | struct IsCopy<T:Copy> { t: T }
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-struct-bound.stderr b/src/test/ui/wf/wf-struct-bound.stderr
index 1fdcced..2028a0b 100644
--- a/src/test/ui/wf/wf-struct-bound.stderr
+++ b/src/test/ui/wf/wf-struct-bound.stderr
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
   --> $DIR/wf-struct-bound.rs:9:1
    |
+LL |   trait ExtraCopy<T:Copy> { }
+   |   ----------------------- required by `ExtraCopy`
+LL | 
 LL | / struct SomeStruct<T,U>
 LL | |     where T: ExtraCopy<U>
 LL | | {
@@ -9,11 +12,6 @@
    | |_^ the trait `std::marker::Copy` is not implemented for `U`
    |
    = help: consider adding a `where U: std::marker::Copy` bound
-note: required by `ExtraCopy`
-  --> $DIR/wf-struct-bound.rs:7:1
-   |
-LL | trait ExtraCopy<T:Copy> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-struct-field.stderr b/src/test/ui/wf/wf-struct-field.stderr
index e609f93..d2bff25 100644
--- a/src/test/ui/wf/wf-struct-field.stderr
+++ b/src/test/ui/wf/wf-struct-field.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied
   --> $DIR/wf-struct-field.rs:12:5
    |
+LL | struct IsCopy<T:Copy> {
+   | --------------------- required by `IsCopy`
+...
 LL |     data: IsCopy<A>
    |     ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A`
    |
    = help: consider adding a `where A: std::marker::Copy` bound
-note: required by `IsCopy`
-  --> $DIR/wf-struct-field.rs:7:1
-   |
-LL | struct IsCopy<T:Copy> {
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-associated-type-bound.stderr b/src/test/ui/wf/wf-trait-associated-type-bound.stderr
index 658d412..d5b2b57 100644
--- a/src/test/ui/wf/wf-trait-associated-type-bound.stderr
+++ b/src/test/ui/wf/wf-trait-associated-type-bound.stderr
@@ -1,17 +1,15 @@
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/wf-trait-associated-type-bound.rs:9:1
    |
+LL |   trait ExtraCopy<T:Copy> { }
+   |   ----------------------- required by `ExtraCopy`
+LL | 
 LL | / trait SomeTrait<T> {
 LL | |     type Type1: ExtraCopy<T>;
 LL | | }
    | |_^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `ExtraCopy`
-  --> $DIR/wf-trait-associated-type-bound.rs:7:1
-   |
-LL | trait ExtraCopy<T:Copy> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.stderr b/src/test/ui/wf/wf-trait-associated-type-trait.stderr
index 70fabcd..d8ab955 100644
--- a/src/test/ui/wf/wf-trait-associated-type-trait.stderr
+++ b/src/test/ui/wf/wf-trait-associated-type-trait.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `<Self as SomeTrait>::Type1: std::marker::Copy` is not satisfied
   --> $DIR/wf-trait-associated-type-trait.rs:11:5
    |
+LL | struct IsCopy<T:Copy> { x: T }
+   | --------------------- required by `IsCopy`
+...
 LL |     type Type2 = IsCopy<Self::Type1>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `<Self as SomeTrait>::Type1`
    |
    = help: consider adding a `where <Self as SomeTrait>::Type1: std::marker::Copy` bound
-note: required by `IsCopy`
-  --> $DIR/wf-trait-associated-type-trait.rs:7:1
-   |
-LL | struct IsCopy<T:Copy> { x: T }
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-bound.stderr b/src/test/ui/wf/wf-trait-bound.stderr
index 5cc9451..85f12b2 100644
--- a/src/test/ui/wf/wf-trait-bound.stderr
+++ b/src/test/ui/wf/wf-trait-bound.stderr
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
   --> $DIR/wf-trait-bound.rs:9:1
    |
+LL |   trait ExtraCopy<T:Copy> { }
+   |   ----------------------- required by `ExtraCopy`
+LL | 
 LL | / trait SomeTrait<T,U>
 LL | |     where T: ExtraCopy<U>
 LL | | {
@@ -8,11 +11,6 @@
    | |_^ the trait `std::marker::Copy` is not implemented for `U`
    |
    = help: consider adding a `where U: std::marker::Copy` bound
-note: required by `ExtraCopy`
-  --> $DIR/wf-trait-bound.rs:7:1
-   |
-LL | trait ExtraCopy<T:Copy> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr
index e713389..4d0e1f2 100644
--- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr
+++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
   --> $DIR/wf-trait-default-fn-arg.rs:11:5
    |
+LL |   struct Bar<T:Eq+?Sized> { value: Box<T> }
+   |   ----------------------- required by `Bar`
+...
 LL | /     fn bar(&self, x: &Bar<Self>) {
 LL | |
 LL | |         //
@@ -9,11 +12,6 @@
    | |_____^ the trait `std::cmp::Eq` is not implemented for `Self`
    |
    = help: consider adding a `where Self: std::cmp::Eq` bound
-note: required by `Bar`
-  --> $DIR/wf-trait-default-fn-arg.rs:8:1
-   |
-LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-default-fn-ret.stderr b/src/test/ui/wf/wf-trait-default-fn-ret.stderr
index 5a310a8..e82b76b 100644
--- a/src/test/ui/wf/wf-trait-default-fn-ret.stderr
+++ b/src/test/ui/wf/wf-trait-default-fn-ret.stderr
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
   --> $DIR/wf-trait-default-fn-ret.rs:11:5
    |
+LL |   struct Bar<T:Eq+?Sized> { value: Box<T> }
+   |   ----------------------- required by `Bar`
+...
 LL | /     fn bar(&self) -> Bar<Self> {
 LL | |
 LL | |         //
@@ -10,11 +13,6 @@
    | |_____^ the trait `std::cmp::Eq` is not implemented for `Self`
    |
    = help: consider adding a `where Self: std::cmp::Eq` bound
-note: required by `Bar`
-  --> $DIR/wf-trait-default-fn-ret.rs:8:1
-   |
-LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr
index d5a00be..6504f66 100644
--- a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr
+++ b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
   --> $DIR/wf-trait-default-fn-where-clause.rs:11:5
    |
+LL |   trait Bar<T:Eq+?Sized> { }
+   |   ---------------------- required by `Bar`
+...
 LL | /     fn bar<A>(&self) where A: Bar<Self> {
 LL | |
 LL | |         //
@@ -9,11 +12,6 @@
    | |_____^ the trait `std::cmp::Eq` is not implemented for `Self`
    |
    = help: consider adding a `where Self: std::cmp::Eq` bound
-note: required by `Bar`
-  --> $DIR/wf-trait-default-fn-where-clause.rs:8:1
-   |
-LL | trait Bar<T:Eq+?Sized> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr
index 2b26eac..0887d4b 100644
--- a/src/test/ui/wf/wf-trait-fn-arg.stderr
+++ b/src/test/ui/wf/wf-trait-fn-arg.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
   --> $DIR/wf-trait-fn-arg.rs:10:5
    |
+LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
+   | ----------------------- required by `Bar`
+...
 LL |     fn bar(&self, x: &Bar<Self>);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self`
    |
    = help: consider adding a `where Self: std::cmp::Eq` bound
-note: required by `Bar`
-  --> $DIR/wf-trait-fn-arg.rs:7:1
-   |
-LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-fn-ret.stderr b/src/test/ui/wf/wf-trait-fn-ret.stderr
index 70f07f0..5555081 100644
--- a/src/test/ui/wf/wf-trait-fn-ret.stderr
+++ b/src/test/ui/wf/wf-trait-fn-ret.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
   --> $DIR/wf-trait-fn-ret.rs:10:5
    |
+LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
+   | ----------------------- required by `Bar`
+...
 LL |     fn bar(&self) -> &Bar<Self>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self`
    |
    = help: consider adding a `where Self: std::cmp::Eq` bound
-note: required by `Bar`
-  --> $DIR/wf-trait-fn-ret.rs:7:1
-   |
-LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-fn-where-clause.stderr
index 2d6223e..5e8fd89 100644
--- a/src/test/ui/wf/wf-trait-fn-where-clause.stderr
+++ b/src/test/ui/wf/wf-trait-fn-where-clause.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
   --> $DIR/wf-trait-fn-where-clause.rs:10:5
    |
+LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
+   | ----------------------- required by `Bar`
+...
 LL |     fn bar(&self) where Self: Sized, Bar<Self>: Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self`
    |
    = help: consider adding a `where Self: std::cmp::Eq` bound
-note: required by `Bar`
-  --> $DIR/wf-trait-fn-where-clause.rs:7:1
-   |
-LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-superbound.stderr b/src/test/ui/wf/wf-trait-superbound.stderr
index a3c4ab5..377ca64 100644
--- a/src/test/ui/wf/wf-trait-superbound.stderr
+++ b/src/test/ui/wf/wf-trait-superbound.stderr
@@ -1,16 +1,14 @@
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/wf-trait-superbound.rs:9:1
    |
+LL |   trait ExtraCopy<T:Copy> { }
+   |   ----------------------- required by `ExtraCopy`
+LL | 
 LL | / trait SomeTrait<T>: ExtraCopy<T> {
 LL | | }
    | |_^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `ExtraCopy`
-  --> $DIR/wf-trait-superbound.rs:7:1
-   |
-LL | trait ExtraCopy<T:Copy> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
index 125b65b..f923c67 100644
--- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
+++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:9
    |
+LL | fn require_copy<T: Copy>(x: T) {}
+   | ------------------------------ required by `require_copy`
+...
 LL |         require_copy(self.x);
    |         ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `require_copy`
-  --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:1
-   |
-LL | fn require_copy<T: Copy>(x: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
index eb555b1..3273683 100644
--- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
+++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
@@ -1,15 +1,13 @@
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
   --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:9
    |
+LL | fn require_copy<T: Copy>(x: T) {}
+   | ------------------------------ required by `require_copy`
+...
 LL |         require_copy(self.x);
    |         ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
-note: required by `require_copy`
-  --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:1
-   |
-LL | fn require_copy<T: Copy>(x: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr
index fb69e2d..e59d608 100644
--- a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr
+++ b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr
@@ -1,14 +1,11 @@
 error[E0277]: the trait bound `Struct: std::cmp::Eq` is not satisfied
   --> $DIR/where-clauses-unsatisfied.rs:6:10
    |
+LL | fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b }
+   | ---------------------------------------------- required by `equal`
+...
 LL |     drop(equal(&Struct, &Struct))
    |          ^^^^^ the trait `std::cmp::Eq` is not implemented for `Struct`
-   |
-note: required by `equal`
-  --> $DIR/where-clauses-unsatisfied.rs:1:1
-   |
-LL | fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr
index dbe68b8..32dc0e7 100644
--- a/src/test/ui/where-clauses/where-for-self-2.stderr
+++ b/src/test/ui/where-clauses/where-for-self-2.stderr
@@ -1,18 +1,16 @@
 error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied
   --> $DIR/where-for-self-2.rs:21:5
    |
-LL |     foo(&X);
-   |     ^^^ the trait `for<'a> Bar` is not implemented for `&'a _`
-   |
-   = help: the following implementations were found:
-             <&'static u32 as Bar>
-note: required by `foo`
-  --> $DIR/where-for-self-2.rs:16:1
-   |
 LL | / fn foo<T>(x: &T)
 LL | |     where for<'a> &'a T: Bar
 LL | | {}
-   | |__^
+   | |__- required by `foo`
+...
+LL |       foo(&X);
+   |       ^^^ the trait `for<'a> Bar` is not implemented for `&'a _`
+   |
+   = help: the following implementations were found:
+             <&'static u32 as Bar>
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/while-let.rs b/src/test/ui/while-let.rs
index 69f9de9..53babef 100644
--- a/src/test/ui/while-let.rs
+++ b/src/test/ui/while-let.rs
@@ -1,5 +1,6 @@
 // run-pass
 
+#[allow(dead_code)]
 fn macros() {
     macro_rules! foo{
         ($p:pat, $e:expr, $b:block) => {{
@@ -12,16 +13,16 @@
         }}
     }
 
-    foo!(a, 1, { //~ WARN irrefutable while-let
+    foo!(_a, 1, { //~ WARN irrefutable while-let
         println!("irrefutable pattern");
     });
-    bar!(a, 1, { //~ WARN irrefutable while-let
+    bar!(_a, 1, { //~ WARN irrefutable while-let
         println!("irrefutable pattern");
     });
 }
 
 pub fn main() {
-    while let a = 1 { //~ WARN irrefutable while-let
+    while let _a = 1 { //~ WARN irrefutable while-let
         println!("irrefutable pattern");
         break;
     }
diff --git a/src/test/ui/while-let.stderr b/src/test/ui/while-let.stderr
index 348925a..30307ec 100644
--- a/src/test/ui/while-let.stderr
+++ b/src/test/ui/while-let.stderr
@@ -1,10 +1,10 @@
 warning: irrefutable while-let pattern
-  --> $DIR/while-let.rs:6:13
+  --> $DIR/while-let.rs:7:13
    |
 LL |               while let $p = $e $b
    |               ^^^^^
 ...
-LL | /     foo!(a, 1, {
+LL | /     foo!(_a, 1, {
 LL | |         println!("irrefutable pattern");
 LL | |     });
    | |_______- in this macro invocation
@@ -12,20 +12,20 @@
    = note: `#[warn(irrefutable_let_patterns)]` on by default
 
 warning: irrefutable while-let pattern
-  --> $DIR/while-let.rs:6:13
+  --> $DIR/while-let.rs:7:13
    |
 LL |               while let $p = $e $b
    |               ^^^^^
 ...
-LL | /     bar!(a, 1, {
+LL | /     bar!(_a, 1, {
 LL | |         println!("irrefutable pattern");
 LL | |     });
    | |_______- in this macro invocation
 
 warning: irrefutable while-let pattern
-  --> $DIR/while-let.rs:24:5
+  --> $DIR/while-let.rs:25:5
    |
-LL | /     while let a = 1 {
+LL | /     while let _a = 1 {
 LL | |         println!("irrefutable pattern");
 LL | |         break;
 LL | |     }
diff --git a/src/test/ui/wrapping-int-combinations.rs b/src/test/ui/wrapping-int-combinations.rs
new file mode 100644
index 0000000..f0bc479
--- /dev/null
+++ b/src/test/ui/wrapping-int-combinations.rs
@@ -0,0 +1,77 @@
+// run-pass
+
+use std::num::Wrapping;
+
+macro_rules! wrapping_operation {
+    ($result:expr, $lhs:ident $op:tt $rhs:expr) => {
+        assert_eq!($result, $lhs $op $rhs);
+        assert_eq!($result, &$lhs $op $rhs);
+        assert_eq!($result, $lhs $op &$rhs);
+        assert_eq!($result, &$lhs $op &$rhs);
+    };
+    ($result:expr, $op:tt $expr:expr) => {
+        assert_eq!($result, $op $expr);
+        assert_eq!($result, $op &$expr);
+    };
+}
+
+macro_rules! wrapping_assignment {
+    ($result:expr, $lhs:ident $op:tt $rhs:expr) => {
+        let mut lhs1 = $lhs;
+        lhs1 $op $rhs;
+        assert_eq!($result, lhs1);
+
+        let mut lhs2 = $lhs;
+        lhs2 $op &$rhs;
+        assert_eq!($result, lhs2);
+    };
+}
+
+macro_rules! wrapping_test {
+    ($type:ty, $min:expr, $max:expr) => {
+        let zero: Wrapping<$type> = Wrapping(0);
+        let one: Wrapping<$type> = Wrapping(1);
+        let min: Wrapping<$type> = Wrapping($min);
+        let max: Wrapping<$type> = Wrapping($max);
+
+        wrapping_operation!(min, max + one);
+        wrapping_assignment!(min, max += one);
+        wrapping_operation!(max, min - one);
+        wrapping_assignment!(max, min -= one);
+        wrapping_operation!(max, max * one);
+        wrapping_assignment!(max, max *= one);
+        wrapping_operation!(max, max / one);
+        wrapping_assignment!(max, max /= one);
+        wrapping_operation!(zero, max % one);
+        wrapping_assignment!(zero, max %= one);
+        wrapping_operation!(zero, zero & max);
+        wrapping_assignment!(zero, zero &= max);
+        wrapping_operation!(max, zero | max);
+        wrapping_assignment!(max, zero |= max);
+        wrapping_operation!(zero, max ^ max);
+        wrapping_assignment!(zero, max ^= max);
+        wrapping_operation!(zero, zero << 1usize);
+        wrapping_assignment!(zero, zero <<= 1usize);
+        wrapping_operation!(zero, zero >> 1usize);
+        wrapping_assignment!(zero, zero >>= 1usize);
+        wrapping_operation!(zero, -zero);
+        wrapping_operation!(max, !min);
+    };
+}
+
+fn main() {
+    wrapping_test!(i8, std::i8::MIN, std::i8::MAX);
+    wrapping_test!(i16, std::i16::MIN, std::i16::MAX);
+    wrapping_test!(i32, std::i32::MIN, std::i32::MAX);
+    wrapping_test!(i64, std::i64::MIN, std::i64::MAX);
+    #[cfg(not(target_os = "emscripten"))]
+    wrapping_test!(i128, std::i128::MIN, std::i128::MAX);
+    wrapping_test!(isize, std::isize::MIN, std::isize::MAX);
+    wrapping_test!(u8, std::u8::MIN, std::u8::MAX);
+    wrapping_test!(u16, std::u16::MIN, std::u16::MAX);
+    wrapping_test!(u32, std::u32::MIN, std::u32::MAX);
+    wrapping_test!(u64, std::u64::MIN, std::u64::MAX);
+    #[cfg(not(target_os = "emscripten"))]
+    wrapping_test!(u128, std::u128::MIN, std::u128::MAX);
+    wrapping_test!(usize, std::usize::MIN, std::usize::MAX);
+}
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 9ffa939..eab23f3 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -1,3 +1,9 @@
+//! Build a dist manifest, hash and sign everything.
+//! This gets called by `promote-release`
+//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release)
+//! via `x.py dist hash-and-sign`; the cmdline arguments are set up
+//! by rustbuild (in `src/bootstrap/dist.rs`).
+
 use toml;
 use serde::Serialize;
 
@@ -270,6 +276,7 @@
     // Do not ask for a passphrase while manually testing
     let mut passphrase = String::new();
     if should_sign {
+        // `x.py` passes the passphrase via stdin.
         t!(io::stdin().read_to_string(&mut passphrase));
     }
 
@@ -362,6 +369,7 @@
         }
     }
 
+    /// Hash all files, compute their signatures, and collect the hashes in `self.digests`.
     fn digest_and_sign(&mut self) {
         for file in t!(self.input.read_dir()).map(|e| t!(e).path()) {
             let filename = file.file_name().unwrap().to_str().unwrap();
@@ -532,19 +540,20 @@
             .as_ref()
             .cloned()
             .map(|version| (version, true))
-            .unwrap_or_default();
+            .unwrap_or_default(); // `is_present` defaults to `false` here.
 
-        // miri needs to build std with xargo, which doesn't allow stable/beta:
-        // <https://github.com/japaric/xargo/pull/204#issuecomment-374888868>
+        // Miri is nightly-only; never ship it for other trains.
         if pkgname == "miri-preview" && self.rust_release != "nightly" {
-            is_present = false; // ignore it
+            is_present = false; // Pretend the component is entirely missing.
         }
 
         let targets = targets.iter().map(|name| {
             if is_present {
+                // The component generally exists, but it might still be missing for this target.
                 let filename = self.filename(pkgname, name);
                 let digest = match self.digests.remove(&filename) {
                     Some(digest) => digest,
+                    // This component does not exist for this target -- skip it.
                     None => return (name.to_string(), Target::unavailable()),
                 };
                 let xz_filename = filename.replace(".tar.gz", ".tar.xz");
diff --git a/src/tools/cargo b/src/tools/cargo
index 22f7dd0..9655d70 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 22f7dd0495cd72ce2082d318d5a9b4dccb9c5b8c
+Subproject commit 9655d70af8a6dddac238e3afa2fec75088c9226f
diff --git a/src/tools/clippy b/src/tools/clippy
index a939d61..58e01ea 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit a939d61cf7feac0f328aec07f050c4ac96c51d2c
+Subproject commit 58e01ea4d7df69e658c034afbfa6d0abd90808ed
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index e759ad1..745233c 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -6,7 +6,7 @@
 
 [dependencies]
 diff = "0.1.10"
-env_logger = { version = "0.5", default-features = false }
+env_logger = { version = "0.6", default-features = false }
 getopts = "0.2"
 log = "0.4"
 regex = "1.0"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 66e030e..edb9eb7 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -333,10 +333,12 @@
     testpaths.file.with_extension(extension)
 }
 
-pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED];
+pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT];
 pub const UI_STDERR: &str = "stderr";
 pub const UI_STDOUT: &str = "stdout";
 pub const UI_FIXED: &str = "fixed";
+pub const UI_RUN_STDERR: &str = "run.stderr";
+pub const UI_RUN_STDOUT: &str = "run.stdout";
 
 /// Absolute path to the directory where all output for all tests in the given
 /// `relative_dir` group should reside. Example:
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 076ad87..48dd68d 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -137,6 +137,11 @@
                    config.parse_needs_sanitizer_support(ln) {
                     props.ignore = Ignore::Ignore;
                 }
+
+                if config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln) {
+                    props.ignore = Ignore::Ignore;
+                }
+
             }
 
             if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoGdbLldb) &&
@@ -326,6 +331,8 @@
     pub force_host: bool,
     // Check stdout for error-pattern output as well as stderr
     pub check_stdout: bool,
+    // Check stdout & stderr for output of run-pass test
+    pub check_run_results: bool,
     // For UI tests, allows compiler to generate arbitrary output to stdout
     pub dont_check_compiler_stdout: bool,
     // For UI tests, allows compiler to generate arbitrary output to stderr
@@ -388,6 +395,7 @@
             build_aux_docs: false,
             force_host: false,
             check_stdout: false,
+            check_run_results: false,
             dont_check_compiler_stdout: false,
             dont_check_compiler_stderr: false,
             no_prefer_dynamic: false,
@@ -468,6 +476,10 @@
                 self.check_stdout = config.parse_check_stdout(ln);
             }
 
+            if !self.check_run_results {
+                self.check_run_results = config.parse_check_run_results(ln);
+            }
+
             if !self.dont_check_compiler_stdout {
                 self.dont_check_compiler_stdout = config.parse_dont_check_compiler_stdout(ln);
             }
@@ -616,6 +628,11 @@
         }
         self.pass_mode
     }
+
+    // does not consider CLI override for pass mode
+    pub fn local_pass_mode(&self) -> Option<PassMode> {
+        self.pass_mode
+    }
 }
 
 fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) {
@@ -712,6 +729,10 @@
         self.parse_name_directive(line, "check-stdout")
     }
 
+    fn parse_check_run_results(&self, line: &str) -> bool {
+        self.parse_name_directive(line, "check-run-results")
+    }
+
     fn parse_dont_check_compiler_stdout(&self, line: &str) -> bool {
         self.parse_name_directive(line, "dont-check-compiler-stdout")
     }
@@ -819,10 +840,10 @@
 
             if name == "test" ||
                 util::matches_os(&self.target, name) ||             // target
+                util::matches_env(&self.target, name) ||            // env
                 name == util::get_arch(&self.target) ||             // architecture
                 name == util::get_pointer_width(&self.target) ||    // pointer width
                 name == self.stage_id.split('-').next().unwrap() || // stage
-                Some(name) == util::get_env(&self.target) ||        // env
                 (self.target != self.host && name == "cross-compile") ||
                 match self.compare_mode {
                     Some(CompareMode::Nll) => name == "compare-mode-nll",
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index bde49ff..7c51de5 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -253,7 +253,7 @@
     if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
         let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
         println!("{}", opts.usage(&message));
-        println!("");
+        println!();
         panic!()
     }
 
@@ -265,7 +265,7 @@
     if matches.opt_present("h") || matches.opt_present("help") {
         let message = format!("Usage: {} [OPTIONS]  [TESTNAME...]", argv0);
         println!("{}", opts.usage(&message));
-        println!("");
+        println!();
         panic!()
     }
 
@@ -335,7 +335,7 @@
         runtool: matches.opt_str("runtool"),
         host_rustcflags: matches.opt_str("host-rustcflags"),
         target_rustcflags: matches.opt_str("target-rustcflags"),
-        target: target,
+        target,
         host: opt_str2(matches.opt_str("host")),
         cdb,
         gdb,
@@ -345,7 +345,7 @@
         lldb_native_rust,
         llvm_version: matches.opt_str("llvm-version"),
         system_llvm: matches.opt_present("system-llvm"),
-        android_cross_path: android_cross_path,
+        android_cross_path,
         adb_path: opt_str2(matches.opt_str("adb-path")),
         adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
         adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 3da6be7..baed27d 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2,6 +2,7 @@
 
 use crate::common::{CompareMode, PassMode};
 use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
+use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT};
 use crate::common::{output_base_dir, output_base_name, output_testname_unique};
 use crate::common::{Codegen, CodegenUnits, Rustdoc};
 use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb};
@@ -288,6 +289,11 @@
     Stdin(String),
 }
 
+enum TestOutput {
+    Compile,
+    Run,
+}
+
 impl<'test> TestCx<'test> {
     /// Code executed for each revision in turn (or, if there are no
     /// revisions, exactly once, with revision == None).
@@ -1551,7 +1557,11 @@
                 // want to actually assert warnings about all this code. Instead
                 // let's just ignore unused code warnings by defaults and tests
                 // can turn it back on if needed.
-                if !self.config.src_base.ends_with("rustdoc-ui") {
+                if !self.config.src_base.ends_with("rustdoc-ui") &&
+                    // Note that we don't call pass_mode() here as we don't want
+                    // to set unused to allow if we've overriden the pass mode
+                    // via command line flags.
+                    self.props.local_pass_mode() != Some(PassMode::Run) {
                     rustc.args(&["-A", "unused"]);
                 }
             }
@@ -1603,11 +1613,7 @@
             .args(&self.props.compile_flags);
 
         if let Some(ref linker) = self.config.linker {
-            rustdoc
-                .arg("--linker")
-                .arg(linker)
-                .arg("-Z")
-                .arg("unstable-options");
+            rustdoc.arg(format!("-Clinker={}", linker));
         }
 
         self.compose_and_run_compiler(rustdoc, None)
@@ -1725,6 +1731,21 @@
         }
     }
 
+    fn is_vxworks_pure_static(&self) -> bool {
+        if self.config.target.contains("vxworks") {
+            match env::var("RUST_VXWORKS_TEST_DYLINK") {
+                Ok(s) => s != "1",
+                _ => true
+            }
+        } else {
+            false
+        }
+    }
+
+    fn is_vxworks_pure_dynamic(&self) -> bool {
+        self.config.target.contains("vxworks") && !self.is_vxworks_pure_static()
+    }
+
     fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes {
         let aux_dir = self.aux_output_dir_name();
 
@@ -1768,6 +1789,7 @@
                     && !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
@@ -1999,7 +2021,8 @@
         }
 
         if !is_rustdoc {
-            if self.config.target == "wasm32-unknown-unknown" {
+            if self.config.target == "wasm32-unknown-unknown"
+                || self.is_vxworks_pure_static() {
                 // rustc.arg("-g"); // get any backtrace at all on errors
             } else if !self.props.no_prefer_dynamic {
                 rustc.args(&["-C", "prefer-dynamic"]);
@@ -2044,7 +2067,8 @@
         }
 
         // Use dynamic musl for tests because static doesn't allow creating dylibs
-        if self.config.host.contains("musl") {
+        if self.config.host.contains("musl")
+            || self.is_vxworks_pure_dynamic() {
             rustc.arg("-Ctarget-feature=-crt-static");
         }
 
@@ -2569,7 +2593,7 @@
                     "  actual:   {}",
                     codegen_units_to_str(&actual_item.codegen_units)
                 );
-                println!("");
+                println!();
             }
         }
 
@@ -2934,6 +2958,61 @@
         }
     }
 
+    fn load_compare_outputs(&self, proc_res: &ProcRes,
+        output_kind: TestOutput, explicit_format: bool) -> usize {
+
+        let (stderr_kind, stdout_kind) = match output_kind {
+            TestOutput::Compile => (UI_STDERR, UI_STDOUT),
+            TestOutput::Run => (UI_RUN_STDERR, UI_RUN_STDOUT)
+        };
+
+        let expected_stderr = self.load_expected_output(stderr_kind);
+        let expected_stdout = self.load_expected_output(stdout_kind);
+
+        let normalized_stdout = match output_kind {
+            TestOutput::Run if self.config.remote_test_client.is_some() => {
+                // When tests are run using the remote-test-client, the string
+                // 'uploaded "$TEST_BUILD_DIR/<test_executable>, waiting for result"'
+                // is printed to stdout by the client and then captured in the ProcRes,
+                // so it needs to be removed when comparing the run-pass test execution output
+                lazy_static! {
+                    static ref REMOTE_TEST_RE: Regex = Regex::new(
+                        "^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-]+)+\", waiting for result\n"
+                    ).unwrap();
+                }
+                REMOTE_TEST_RE.replace(
+                    &self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout),
+                    ""
+                ).to_string()
+            }
+            _ => self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout)
+        };
+
+        let stderr = if explicit_format {
+            proc_res.stderr.clone()
+        } else {
+            json::extract_rendered(&proc_res.stderr)
+        };
+
+        let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr);
+        let mut errors = 0;
+        match output_kind {
+            TestOutput::Compile => {
+                if !self.props.dont_check_compiler_stdout {
+                    errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
+                }
+                if !self.props.dont_check_compiler_stderr {
+                    errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr);
+                }
+            }
+            TestOutput::Run => {
+                errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
+                errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
+            }
+        }
+        errors
+    }
+
     fn run_ui_test(&self) {
         // if the user specified a format in the ui test
         // print the output to the stderr file, otherwise extract
@@ -2946,32 +3025,13 @@
         let proc_res = self.compile_test();
         self.check_if_test_should_compile(&proc_res);
 
-        let expected_stderr = self.load_expected_output(UI_STDERR);
-        let expected_stdout = self.load_expected_output(UI_STDOUT);
         let expected_fixed = self.load_expected_output(UI_FIXED);
 
-        let normalized_stdout =
-            self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout);
-
-        let stderr = if explicit {
-            proc_res.stderr.clone()
-        } else {
-            json::extract_rendered(&proc_res.stderr)
-        };
-
-        let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr);
-
-        let mut errors = 0;
-        if !self.props.dont_check_compiler_stdout {
-            errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
-        }
-        if !self.props.dont_check_compiler_stderr {
-            errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr);
-        }
-
         let modes_to_prune = vec![CompareMode::Nll];
         self.prune_duplicate_outputs(&modes_to_prune);
 
+        let mut errors = self.load_compare_outputs(&proc_res, TestOutput::Compile, explicit);
+
         if self.config.compare_mode.is_some() {
             // don't test rustfix with nll right now
         } else if self.config.rustfix_coverage {
@@ -3049,7 +3109,17 @@
 
         if self.should_run_successfully() {
             let proc_res = self.exec_compiled_test();
-
+            let run_output_errors = if self.props.check_run_results {
+                self.load_compare_outputs(&proc_res, TestOutput::Run, explicit)
+            } else {
+                0
+            };
+            if run_output_errors > 0 {
+                self.fatal_proc_rec(
+                    &format!("{} errors occured comparing run output.", run_output_errors),
+                    &proc_res,
+                );
+            }
             if !proc_res.status.success() {
                 self.fatal_proc_rec("test run failed!", &proc_res);
             }
@@ -3456,7 +3526,7 @@
                             }
                         }
                     }
-                    println!("");
+                    println!();
                 }
             }
         }
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 56ebea7..3a2ee44 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -105,8 +105,12 @@
     panic!("Cannot determine Architecture from triple");
 }
 
-pub fn get_env(triple: &str) -> Option<&str> {
-    triple.split('-').nth(3)
+pub fn matches_env(triple: &str, name: &str) -> bool {
+    if let Some(env) = triple.split('-').nth(3) {
+        env.starts_with(name)
+    } else {
+        false
+    }
 }
 
 pub fn get_pointer_width(triple: &str) -> &'static str {
diff --git a/src/tools/error_index_generator/build.rs b/src/tools/error_index_generator/build.rs
index 2ac7351..592b3f1 100644
--- a/src/tools/error_index_generator/build.rs
+++ b/src/tools/error_index_generator/build.rs
@@ -14,9 +14,7 @@
         if entry.file_name() == "error_codes.rs" {
             println!("cargo:rerun-if-changed={}", entry.path().to_str().unwrap());
             let file = fs::read_to_string(entry.path()).unwrap()
-                .replace("use syntax::{register_diagnostics, register_long_diagnostics};", "")
-                .replace("use syntax::register_diagnostics;", "")
-                .replace("use syntax::register_long_diagnostics;", "");
+                .replace("syntax::register_diagnostics!", "register_diagnostics!");
             let contents = format!("(|| {{\n{}\n}})();", file);
 
             fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap();
@@ -26,36 +24,31 @@
     }
 
     let mut all = String::new();
-    all.push_str("fn register_all() -> Vec<(&'static str, Option<&'static str>)> {\n");
-    all.push_str("let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new();\n");
-    all.push_str(r#"
-macro_rules! register_diagnostics {
-    ($($code:tt),*) => {{
-        long_codes.extend([$(
-            stringify!($code),
-        )*].iter().cloned().map(|s| (s, None)).collect::<Vec<_>>());
-    }};
-    ($($code:tt),*,) => {{
-        long_codes.extend([$(
-            stringify!($code),
-        )*].iter().cloned().map(|s| (s, None)));
-    }}
-}
+    all.push_str(r###"
+fn register_all() -> Vec<(&'static str, Option<&'static str>)> {
+    let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new();
+    macro_rules! register_diagnostics {
+        ($($ecode:ident: $message:expr,)*) => (
+            register_diagnostics!{$($ecode:$message,)* ;}
+        );
 
-macro_rules! register_long_diagnostics {
-    ($($code:tt: $description:tt),*) => {
-        {long_codes.extend([$(
-            (stringify!($code), Some(stringify!($description))),
-        )*].iter());}
-    };
-    ($($code:tt: $description:tt),*,) => {
-        {long_codes.extend([$(
-            (stringify!($code), Some(stringify!($description))),
-        )*].iter());}
+        ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
+            $(
+                {long_codes.extend([
+                    (stringify!($ecode), Some($message)),
+                ].iter());}
+            )*
+            $(
+                {long_codes.extend([
+                    stringify!($code),
+                ].iter().cloned().map(|s| (s, None)).collect::<Vec<_>>());}
+            )*
+        )
     }
-}"#);
+"###);
     for idx in 0..idx {
         all.push_str(&format!(r#"include!(concat!(env!("OUT_DIR"), "/error_{}.rs"));"#, idx));
+        all.push_str("\n");
     }
     all.push_str("\nlong_codes\n");
     all.push_str("}\n");
diff --git a/src/tools/miri b/src/tools/miri
index 69268fb..130f948 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit 69268fb75fdb452296caa9bc4aaeff1674279de2
+Subproject commit 130f9488d3b861e02c9282b686eec717e30912cf
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 1411f4c..7cf3cc7 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -7,6 +7,8 @@
 ## It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts
 ## when a new commit lands on `master` (i.e., after it passed all checks on `auto`).
 
+from __future__ import print_function
+
 import sys
 import re
 import os
@@ -20,21 +22,26 @@
     import urllib.request as urllib2
 
 # List of people to ping when the status of a tool or a book changed.
+# These should be collaborators of the rust-lang/rust repository (with at least
+# read privileges on it). CI will fail otherwise.
 MAINTAINERS = {
-    'miri': '@oli-obk @RalfJung @eddyb',
-    'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch @flip1995',
-    'rls': '@Xanewok',
-    'rustfmt': '@topecongiro',
-    'book': '@carols10cents @steveklabnik',
-    'nomicon': '@frewsxcv @Gankro',
-    'reference': '@steveklabnik @Havvy @matthewjasper @ehuss',
-    'rust-by-example': '@steveklabnik @marioidival @projektir',
-    'embedded-book': (
-        '@adamgreig @andre-richter @jamesmunns @korken89 '
-        '@ryankurte @thejpster @therealprof'
-    ),
-    'edition-guide': '@ehuss @Centril @steveklabnik',
-    'rustc-guide': '@mark-i-m @spastorino @amanjeev'
+    'miri': {'oli-obk', 'RalfJung', 'eddyb'},
+    'clippy-driver': {
+        'Manishearth', 'llogiq', 'mcarton', 'oli-obk', 'phansch', 'flip1995',
+        'yaahc',
+    },
+    'rls': {'Xanewok'},
+    'rustfmt': {'topecongiro'},
+    'book': {'carols10cents', 'steveklabnik'},
+    'nomicon': {'frewsxcv', 'Gankra'},
+    'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'},
+    'rust-by-example': {'steveklabnik', 'marioidival'},
+    'embedded-book': {
+        'adamgreig', 'andre-richter', 'jamesmunns', 'korken89',
+        'ryankurte', 'thejpster', 'therealprof',
+    },
+    'edition-guide': {'ehuss', 'Centril', 'steveklabnik'},
+    'rustc-guide': {'mark-i-m', 'spastorino', 'amanjeev'},
 }
 
 REPOS = {
@@ -52,6 +59,50 @@
 }
 
 
+def validate_maintainers(repo, github_token):
+    '''Ensure all maintainers are assignable on a GitHub repo'''
+    next_link_re = re.compile(r'<([^>]+)>; rel="next"')
+
+    # Load the list of assignable people in the GitHub repo
+    assignable = []
+    url = 'https://api.github.com/repos/%s/collaborators?per_page=100' % repo
+    while url is not None:
+        response = urllib2.urlopen(urllib2.Request(url, headers={
+            'Authorization': 'token ' + github_token,
+            # Properly load nested teams.
+            'Accept': 'application/vnd.github.hellcat-preview+json',
+        }))
+        assignable.extend(user['login'] for user in json.load(response))
+        # Load the next page if available
+        url = None
+        link_header = response.headers.get('Link')
+        if link_header:
+            matches = next_link_re.match(link_header)
+            if matches is not None:
+                url = matches.group(1)
+
+    errors = False
+    for tool, maintainers in MAINTAINERS.items():
+        for maintainer in maintainers:
+            if maintainer not in assignable:
+                errors = True
+                print(
+                    "error: %s maintainer @%s is not assignable in the %s repo"
+                    % (tool, maintainer, repo),
+                )
+
+    if errors:
+        print()
+        print("  To be assignable, a person needs to be explicitly listed as a")
+        print("  collaborator in the repository settings. The simple way to")
+        print("  fix this is to ask someone with 'admin' privileges on the repo")
+        print("  to add the person or whole team as a collaborator with 'read'")
+        print("  privileges. Those privileges don't grant any extra permissions")
+        print("  so it's safe to apply them.")
+        print()
+        print("The build will fail due to this.")
+        exit(1)
+
 def read_current_status(current_commit, path):
     '''Reads build status of `current_commit` from content of `history/*.tsv`
     '''
@@ -73,13 +124,12 @@
 def issue(
     tool,
     status,
-    maintainers,
+    assignees,
     relevant_pr_number,
     relevant_pr_user,
     pr_reviewer,
 ):
     # Open an issue about the toolstate failure.
-    assignees = [x.strip() for x in maintainers.split('@') if x != '']
     if status == 'test-fail':
         status_description = 'has failing tests'
     else:
@@ -100,7 +150,7 @@
             REPOS.get(tool), relevant_pr_user, pr_reviewer
         )),
         'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
-        'assignees': assignees,
+        'assignees': list(assignees),
         'labels': ['T-compiler', 'I-nominated'],
     })
     print("Creating issue:\n{}".format(request))
@@ -150,22 +200,32 @@
                 old = status[os]
                 new = s.get(tool, old)
                 status[os] = new
-                if new > old: # comparing the strings, but they are ordered appropriately!
+                maintainers = ' '.join('@'+name for name in MAINTAINERS[tool])
+                # comparing the strings, but they are ordered appropriately:
+                # "test-pass" > "test-fail" > "build-fail"
+                if new > old:
                     # things got fixed or at least the status quo improved
                     changed = True
                     message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
-                        .format(tool, os, old, new, MAINTAINERS.get(tool))
+                        .format(tool, os, old, new, maintainers)
                 elif new < old:
                     # tests or builds are failing and were not failing before
                     changed = True
                     title = '💔 {} on {}: {} → {}' \
                         .format(tool, os, old, new)
                     message += '{} (cc {}, @rust-lang/infra).\n' \
-                        .format(title, MAINTAINERS.get(tool))
-                    # Most tools only create issues for build failures.
-                    # Other failures can be spurious.
-                    if new == 'build-fail' or (tool == 'miri' and new == 'test-fail'):
-                        create_issue_for_status = new
+                        .format(title, maintainers)
+                    # See if we need to create an issue.
+                    if tool == 'miri':
+                        # Create issue if tests used to pass before. Don't open a *second*
+                        # issue when we regress from "test-fail" to "build-fail".
+                        if old == 'test-pass':
+                            create_issue_for_status = new
+                    else:
+                        # Create issue if things no longer build.
+                        # (No issue for mere test failures to avoid spurious issues.)
+                        if new == 'build-fail':
+                            create_issue_for_status = new
 
             if create_issue_for_status is not None:
                 try:
@@ -200,6 +260,16 @@
 
 
 if __name__ == '__main__':
+    repo = os.environ.get('TOOLSTATE_VALIDATE_MAINTAINERS_REPO')
+    if repo:
+        github_token = os.environ.get('TOOLSTATE_REPO_ACCESS_TOKEN')
+        if github_token:
+            validate_maintainers(repo, github_token)
+        else:
+            print('skipping toolstate maintainers validation since no GitHub token is present')
+        # When validating maintainers don't run the full script.
+        exit(0)
+
     cur_commit = sys.argv[1]
     cur_datetime = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
     cur_commit_msg = sys.argv[2]
diff --git a/src/tools/rls b/src/tools/rls
index 496c892..d9aa23a 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 496c89275221303a4b0c2779cb8203fb3ce2a136
+Subproject commit d9aa23a43ad29e3a10551a1425ef5d5baef28d70
diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs
index 95530b2..d5dc9a7 100644
--- a/src/tools/rustbook/src/main.rs
+++ b/src/tools/rustbook/src/main.rs
@@ -1,18 +1,19 @@
-use clap::{crate_version};
+use clap::crate_version;
 
 use std::env;
 use std::path::{Path, PathBuf};
 
-use clap::{App, ArgMatches, SubCommand, AppSettings};
+use clap::{App, AppSettings, ArgMatches, SubCommand};
 
+use mdbook::errors::Result as Result3;
 use mdbook::MDBook;
-use mdbook::errors::{Result as Result3};
 
 #[cfg(feature = "linkcheck")]
+use failure::Error;
+#[cfg(feature = "linkcheck")]
 use mdbook::renderer::RenderContext;
 #[cfg(feature = "linkcheck")]
 use mdbook_linkcheck::{self, errors::BrokenLinks};
-use failure::Error;
 
 fn main() {
     let d_message = "-d, --dest-dir=[dest-dir]
@@ -21,18 +22,22 @@
 'A directory for your book{n}(Defaults to Current Directory when omitted)'";
 
     let matches = App::new("rustbook")
-                    .about("Build a book with mdBook")
-                    .author("Steve Klabnik <steve@steveklabnik.com>")
-                    .version(&*format!("v{}", crate_version!()))
-                    .setting(AppSettings::SubcommandRequired)
-                    .subcommand(SubCommand::with_name("build")
-                        .about("Build the book from the markdown files")
-                        .arg_from_usage(d_message)
-                        .arg_from_usage(dir_message))
-                    .subcommand(SubCommand::with_name("linkcheck")
-                        .about("Run linkcheck with mdBook 3")
-                        .arg_from_usage(dir_message))
-                    .get_matches();
+        .about("Build a book with mdBook")
+        .author("Steve Klabnik <steve@steveklabnik.com>")
+        .version(&*format!("v{}", crate_version!()))
+        .setting(AppSettings::SubcommandRequired)
+        .subcommand(
+            SubCommand::with_name("build")
+                .about("Build the book from the markdown files")
+                .arg_from_usage(d_message)
+                .arg_from_usage(dir_message),
+        )
+        .subcommand(
+            SubCommand::with_name("linkcheck")
+                .about("Run linkcheck with mdBook 3")
+                .arg_from_usage(dir_message),
+        )
+        .get_matches();
 
     // Check which subcomamnd the user ran...
     match matches.subcommand() {
@@ -46,23 +51,44 @@
 
                 ::std::process::exit(101);
             }
-        },
+        }
         ("linkcheck", Some(sub_matches)) => {
-            if let Err(err) = linkcheck(sub_matches) {
-                eprintln!("Error: {}", err);
+            #[cfg(feature = "linkcheck")]
+            {
+                if let Err(err) = linkcheck(sub_matches) {
+                    eprintln!("Error: {}", err);
 
-                #[cfg(feature = "linkcheck")]
-                {
-                    if let Ok(broken_links) = err.downcast::<BrokenLinks>() {
-                        for cause in broken_links.links().iter() {
-                            eprintln!("\tCaused By: {}", cause);
-                        }
+                    // HACK: ignore timeouts
+                    let actually_broken = err
+                        .downcast::<BrokenLinks>()
+                        .map(|broken_links| {
+                            broken_links
+                                .links()
+                                .iter()
+                                .inspect(|cause| eprintln!("\tCaused By: {}", cause))
+                                .fold(false, |already_broken, cause| {
+                                    already_broken || !format!("{}", cause).contains("timed out")
+                                })
+                        })
+                        .unwrap_or(false);
+
+                    if actually_broken {
+                        std::process::exit(101);
+                    } else {
+                        std::process::exit(0);
                     }
                 }
-
-                ::std::process::exit(101);
             }
-        },
+
+            #[cfg(not(feature = "linkcheck"))]
+            {
+                // This avoids the `unused_binding` lint.
+                println!(
+                    "mdbook-linkcheck is disabled, but arguments were passed: {:?}",
+                    sub_matches
+                );
+            }
+        }
         (_, _) => unreachable!(),
     };
 }
@@ -77,12 +103,6 @@
     mdbook_linkcheck::check_links(&render_ctx)
 }
 
-#[cfg(not(feature = "linkcheck"))]
-pub fn linkcheck(_args: &ArgMatches<'_>) -> Result<(), Error> {
-    println!("mdbook-linkcheck is disabled.");
-    Ok(())
-}
-
 // Build command implementation
 pub fn build(args: &ArgMatches<'_>) -> Result3<()> {
     let book_dir = get_book_dir(args);
diff --git a/src/tools/rustc-std-workspace-alloc/Cargo.toml b/src/tools/rustc-std-workspace-alloc/Cargo.toml
index ef7dc81..9e04b14 100644
--- a/src/tools/rustc-std-workspace-alloc/Cargo.toml
+++ b/src/tools/rustc-std-workspace-alloc/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rustc-std-workspace-alloc"
-version = "1.0.0"
+version = "1.99.0"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 license = 'MIT OR Apache-2.0'
 description = """
diff --git a/src/tools/rustc-std-workspace-core/Cargo.toml b/src/tools/rustc-std-workspace-core/Cargo.toml
index 38ca56a..6b4e754 100644
--- a/src/tools/rustc-std-workspace-core/Cargo.toml
+++ b/src/tools/rustc-std-workspace-core/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rustc-std-workspace-core"
-version = "1.0.0"
+version = "1.99.0"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 license = 'MIT OR Apache-2.0'
 description = """
diff --git a/src/tools/rustc-std-workspace-std/Cargo.toml b/src/tools/rustc-std-workspace-std/Cargo.toml
index ce16448..e41554b 100644
--- a/src/tools/rustc-std-workspace-std/Cargo.toml
+++ b/src/tools/rustc-std-workspace-std/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rustc-std-workspace-std"
-version = "1.0.0"
+version = "1.99.0"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 license = 'MIT OR Apache-2.0'
 description = """
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index 4ce4112..930279c 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -14,12 +14,6 @@
 # For documentation about what this is and why in the world these dependencies
 # are appearing, see `README.md`.
 
-[build-dependencies]
-# Currently Cargo/RLS depend on `failure` which depends on `synstructure` which
-# enables this feature. Clippy, however, does not depend on anything that
-# enables this feature. Enable it unconditionally.
-syn = { version = "0.15", features = ['extra-traits'] }
-
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
 features = [
@@ -65,14 +59,9 @@
 [dependencies]
 curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
 crossbeam-utils = { version = "0.6.5", features = ["nightly"] }
-parking_lot = { version = "0.7", features = ['nightly'] }
-rand = { version = "0.6.1", features = ["i128_support"] }
 serde = { version = "1.0.82", features = ['derive'] }
 serde_json = { version = "1.0.31", features = ["raw_value"] }
 smallvec = { version = "0.6", features = ['union', 'may_dangle'] }
-scopeguard = { version = "0.3.3", features = ["use_std", "default"] }
-byteorder = { version = "1.2.7", features = ["i128"] }
-syn = { version = "0.15.35", features = ["extra-traits", "full"] }
 
 
 [target.'cfg(not(windows))'.dependencies]
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
index 9792ff0..afb1ee1 160000
--- a/src/tools/rustfmt
+++ b/src/tools/rustfmt
@@ -1 +1 @@
-Subproject commit 9792ff05297c0a5c40942b346c9b0341b9e7c0ee
+Subproject commit afb1ee1c14594aed5bb4a762b357b01f13c9de10
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index a564b99..1ed39f4 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -15,6 +15,7 @@
     "Apache-2.0 / MIT",
     "MIT OR Apache-2.0",
     "Apache-2.0 OR MIT",
+    "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license
     "MIT",
     "Unlicense/MIT",
     "Unlicense OR MIT",
@@ -172,6 +173,7 @@
     Crate("vcpkg"),
     Crate("version_check"),
     Crate("void"),
+    Crate("wasi"),
     Crate("winapi"),
     Crate("winapi-build"),
     Crate("winapi-i686-pc-windows-gnu"),
diff --git a/src/tools/tidy/src/features/tests.rs b/src/tools/tidy/src/features/tests.rs
index fa7a931..994523a 100644
--- a/src/tools/tidy/src/features/tests.rs
+++ b/src/tools/tidy/src/features/tests.rs
@@ -2,8 +2,8 @@
 
 #[test]
 fn test_find_attr_val() {
-    let s = r#"#[unstable(feature = "checked_duration_since", issue = "58402")]"#;
-    assert_eq!(find_attr_val(s, "feature"), Some("checked_duration_since"));
+    let s = r#"#[unstable(feature = "tidy_test_never_used_anywhere_else", issue = "58402")]"#;
+    assert_eq!(find_attr_val(s, "feature"), Some("tidy_test_never_used_anywhere_else"));
     assert_eq!(find_attr_val(s, "issue"), Some("58402"));
     assert_eq!(find_attr_val(s, "since"), None);
 }
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 6a0d530..9302909 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -15,6 +15,7 @@
 
 use std::path::Path;
 
+const ERROR_CODE_COLS: usize = 80;
 const COLS: usize = 100;
 
 const LINES: usize = 3000;
@@ -51,7 +52,13 @@
 /// Lines of this form are allowed to be overlength, because Markdown
 /// offers no way to split a line in the middle of a URL, and the lengths
 /// of URLs to external references are beyond our control.
-fn line_is_url(line: &str) -> bool {
+fn line_is_url(columns: usize, line: &str) -> bool {
+    // more basic check for error_codes.rs, to avoid complexity in implementing two state machines
+    if columns == ERROR_CODE_COLS {
+        return line.starts_with("[") &&
+            line.contains("]:") && line.contains("http");
+    }
+
     use self::LIUState::*;
     let mut state: LIUState = EXP_COMMENT_START;
     let is_url = |w: &str| w.starts_with("http://") || w.starts_with("https://");
@@ -75,7 +82,7 @@
                 => state = EXP_END,
 
             (_, w)
-                if w.len() > COLS && is_url(w)
+                if w.len() > columns && is_url(w)
                 => state = EXP_END,
 
             (_, _) => {}
@@ -88,8 +95,8 @@
 /// Returns `true` if `line` is allowed to be longer than the normal limit.
 /// Currently there is only one exception, for long URLs, but more
 /// may be added in the future.
-fn long_line_is_ok(line: &str) -> bool {
-    if line_is_url(line) {
+fn long_line_is_ok(max_columns: usize, line: &str) -> bool {
+    if line_is_url(max_columns, line) {
         return true;
     }
 
@@ -144,6 +151,12 @@
             tidy_error!(bad, "{}: empty file", file.display());
         }
 
+        let max_columns = if filename == "error_codes.rs" {
+            ERROR_CODE_COLS
+        } else {
+            COLS
+        };
+
         let can_contain = contents.contains("// ignore-tidy-") ||
             contents.contains("# ignore-tidy-");
         let mut skip_cr = contains_ignore_directive(can_contain, &contents, "cr");
@@ -162,11 +175,12 @@
             let mut err = |msg: &str| {
                 tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
             };
-            if line.chars().count() > COLS && !long_line_is_ok(line) {
+            if line.chars().count() > max_columns &&
+                !long_line_is_ok(max_columns, line) {
                 suppressible_tidy_err!(
                     err,
                     skip_line_length,
-                    &format!("line longer than {} chars", COLS)
+                    &format!("line longer than {} chars", max_columns)
                 );
             }
             if line.contains('\t') {